1use super::error::ValidateError;
6use super::parser::PolicyCursor;
7use super::{
8 Array, Counted, PolicyValidationContext, Validate, ValidateArray, array_type,
9 array_type_validate_deref_both,
10};
11
12use std::cmp::Ordering;
13use zerocopy::{FromBytes, Immutable, KnownLayout, Unaligned, little_endian as le};
14
15pub(super) const MAX_BITMAP_ITEMS: u32 = 0x40;
17
18pub(super) const MAP_NODE_BITS: u32 = 8 * std::mem::size_of::<u64>() as u32;
20
21array_type!(ExtensibleBitmap, Metadata, Vec<MapItem>);
22
23array_type_validate_deref_both!(ExtensibleBitmap);
24
25impl ExtensibleBitmap {
26 pub fn num_elements(&self) -> u32 {
28 self.high_bit()
29 }
30
31 pub fn is_set(&self, index: u32) -> bool {
33 if index > self.high_bit() {
34 return false;
35 }
36
37 let map_items = &self.data;
38 if let Ok(i) = map_items.binary_search_by(|map_item| self.item_ordering(map_item, index)) {
39 let map_item = &map_items[i];
40 let item_index = index - map_item.start_bit.get();
41 return map_item.map.get() & (1 << item_index) != 0;
42 }
43
44 false
45 }
46
47 pub fn indices_of_set_bits<'a>(&'a self) -> impl Iterator<Item = u32> {
49 ExtensibleBitmapSpansIterator::<'a> { bitmap: self, map_item: 0, next_bit: 0 }
50 .flat_map(|span| span.low..=span.high)
51 }
52
53 pub fn spans<'a>(&'a self) -> ExtensibleBitmapSpansIterator<'a> {
56 ExtensibleBitmapSpansIterator::<'a> { bitmap: self, map_item: 0, next_bit: 0 }
57 }
58
59 fn high_bit(&self) -> u32 {
62 self.metadata.high_bit.get()
63 }
64
65 fn item_ordering(&self, map_item: &MapItem, index: u32) -> Ordering {
66 let map_item_start_bit = map_item.start_bit.get();
67 if map_item_start_bit > index {
68 Ordering::Greater
69 } else if map_item_start_bit + self.metadata.map_item_size_bits.get() <= index {
70 Ordering::Less
71 } else {
72 Ordering::Equal
73 }
74 }
75}
76
77#[derive(Debug, Clone, PartialEq)]
81pub(super) struct ExtensibleBitmapSpan {
82 pub low: u32,
83 pub high: u32,
84}
85
86pub(super) struct ExtensibleBitmapSpansIterator<'a> {
88 bitmap: &'a ExtensibleBitmap,
89 map_item: usize, next_bit: u32, }
92
93impl ExtensibleBitmapSpansIterator<'_> {
94 fn next_bit_with_value(&mut self, is_set: bool) -> Option<u32> {
96 let map_item_size_bits = self.bitmap.metadata.map_item_size_bits.get();
97 let num_elements = self.bitmap.num_elements();
98
99 while self.next_bit < num_elements {
100 let (start_bit, map) = self
101 .bitmap
102 .data
103 .get(self.map_item)
104 .map_or((num_elements, 0), |item| (item.start_bit.get(), item.map.get()));
105
106 if start_bit > self.next_bit {
107 if is_set {
108 self.next_bit = start_bit
110 } else {
111 return Some(self.next_bit);
112 }
113 } else {
114 let next_map_item_bit = self.next_bit - start_bit;
116 for map_bit in next_map_item_bit..map_item_size_bits {
117 if ((map & (1 << map_bit)) != 0) == is_set {
118 self.next_bit = start_bit + map_bit;
119 return Some(self.next_bit);
120 }
121 }
122
123 self.next_bit = start_bit + map_item_size_bits;
126 self.map_item += 1;
127 }
128 }
129
130 None
131 }
132}
133
134impl Iterator for ExtensibleBitmapSpansIterator<'_> {
135 type Item = ExtensibleBitmapSpan;
136
137 fn next(&mut self) -> Option<Self::Item> {
139 let low = self.next_bit_with_value(true)?;
140 let high =
142 self.next_bit_with_value(false).unwrap_or_else(|| self.bitmap.num_elements()) - 1;
143 Some(Self::Item { low, high })
144 }
145}
146
147impl Validate for Vec<ExtensibleBitmap> {
148 type Error = <ExtensibleBitmap as Validate>::Error;
149
150 fn validate(&self, context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
151 for extensible_bitmap in self {
152 extensible_bitmap.validate(context)?;
153 }
154
155 Ok(())
156 }
157}
158
159impl Validate for Metadata {
160 type Error = ValidateError;
161
162 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
165 let found_size = self.map_item_size_bits.get();
167 if found_size != MAP_NODE_BITS {
168 return Err(ValidateError::InvalidExtensibleBitmapItemSize { found_size });
169 }
170
171 let found_high_bit = self.high_bit.get();
173 if found_high_bit % found_size != 0 {
174 return Err(ValidateError::MisalignedExtensibleBitmapHighBit {
175 found_size,
176 found_high_bit,
177 });
178 }
179
180 let found_count = self.count.get();
182 if found_count * found_size > found_high_bit {
183 return Err(ValidateError::InvalidExtensibleBitmapHighBit {
184 found_size,
185 found_high_bit,
186 found_count,
187 });
188 }
189 if found_count > MAX_BITMAP_ITEMS {
190 return Err(ValidateError::InvalidExtensibleBitmapCount { found_count });
191 }
192 if found_high_bit != 0 && found_count == 0 {
193 return Err(ValidateError::ExtensibleBitmapNonZeroHighBitAndZeroCount);
194 }
195
196 Ok(())
197 }
198}
199
200#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
201#[repr(C, packed)]
202pub(super) struct Metadata {
203 map_item_size_bits: le::U32,
205 high_bit: le::U32,
207 count: le::U32,
209}
210
211impl Counted for Metadata {
212 fn count(&self) -> u32 {
215 self.count.get()
216 }
217}
218
219#[derive(Clone, Debug, KnownLayout, FromBytes, Immutable, PartialEq, Unaligned)]
220#[repr(C, packed)]
221pub(super) struct MapItem {
222 start_bit: le::U32,
225 map: le::U64,
227}
228
229impl Validate for [MapItem] {
230 type Error = anyhow::Error;
231
232 fn validate(&self, _context: &mut PolicyValidationContext) -> Result<(), Self::Error> {
235 Ok(())
236 }
237}
238
239impl ValidateArray<Metadata, MapItem> for ExtensibleBitmap {
240 type Error = anyhow::Error;
241
242 fn validate_array(
246 _context: &mut PolicyValidationContext,
247 metadata: &Metadata,
248 items: &[MapItem],
249 ) -> Result<(), Self::Error> {
250 let found_size = metadata.map_item_size_bits.get();
251 let found_high_bit = metadata.high_bit.get();
252
253 let mut min_start: u32 = 0;
258 for map_item in items {
259 let found_start_bit = map_item.start_bit.get();
260 if found_start_bit % found_size != 0 {
261 return Err(ValidateError::MisalignedExtensibleBitmapItemStartBit {
262 found_start_bit,
263 found_size,
264 }
265 .into());
266 }
267 if found_start_bit < min_start {
268 return Err(ValidateError::OutOfOrderExtensibleBitmapItems {
269 found_start_bit,
270 min_start,
271 }
272 .into());
273 }
274 min_start = found_start_bit + found_size;
275 }
276
277 if min_start > found_high_bit {
279 return Err(ValidateError::ExtensibleBitmapItemOverflow {
280 found_items_end: min_start,
281 found_high_bit,
282 }
283 .into());
284 }
285
286 Ok(())
287 }
288}
289
290#[cfg(test)]
291mod tests {
292 use super::super::error::ParseError;
293 use super::super::parser::{PolicyCursor, PolicyData};
294 use super::super::testing::{as_parse_error, as_validate_error};
295 use super::super::{Parse, PolicyValidationContext};
296 use super::*;
297
298 use std::borrow::Borrow;
299 use std::sync::Arc;
300
301 macro_rules! parse_test {
302 ($parse_output:ident, $data:expr, $result:tt, $policy_data:tt, $check_impl:block) => {{
303 let data = Arc::new($data);
304 fn check_by_value(
305 $result: Result<($parse_output, PolicyCursor), <$parse_output as Parse>::Error>,
306 $policy_data: &PolicyData,
307 ) -> Option<($parse_output, PolicyCursor)> {
308 $check_impl
309 }
310
311 let by_value_result = $parse_output::parse(PolicyCursor::new(data.clone()));
312 let _ = check_by_value(by_value_result, &data);
313 }};
314 }
315
316 struct ExtensibleBitmapIterator<B: Borrow<ExtensibleBitmap>> {
317 extensible_bitmap: B,
318 i: u32,
319 }
320
321 impl<B: Borrow<ExtensibleBitmap>> Iterator for ExtensibleBitmapIterator<B> {
322 type Item = bool;
323
324 fn next(&mut self) -> Option<Self::Item> {
325 if self.i >= self.extensible_bitmap.borrow().high_bit() {
326 return None;
327 }
328 let value = self.extensible_bitmap.borrow().is_set(self.i);
329 self.i = self.i + 1;
330 Some(value)
331 }
332 }
333
334 impl ExtensibleBitmap {
335 fn iter(&self) -> ExtensibleBitmapIterator<&ExtensibleBitmap> {
336 ExtensibleBitmapIterator { extensible_bitmap: self, i: 0 }
337 }
338 }
339
340 #[test]
341 fn extensible_bitmap_simple() {
342 parse_test!(
343 ExtensibleBitmap,
344 [
345 MAP_NODE_BITS.to_le_bytes().as_slice(), MAP_NODE_BITS.to_le_bytes().as_slice(), (1 as u32).to_le_bytes().as_slice(), (0 as u32).to_le_bytes().as_slice(), (1 as u64).to_le_bytes().as_slice(), ]
351 .concat(),
352 result,
353 _policy_data,
354 {
355 let (extensible_bitmap, tail) = result.expect("parse");
356 assert_eq!(24, tail.offset());
357 let mut count: u32 = 0;
358 for (i, bit) in extensible_bitmap.iter().enumerate() {
359 assert!((i == 0 && bit) || (i > 0 && !bit));
360 count = count + 1;
361 }
362 assert_eq!(MAP_NODE_BITS, count);
363 Some((extensible_bitmap, tail))
364 }
365 );
366 }
367
368 #[test]
369 fn extensible_bitmap_sparse_two_item() {
370 parse_test!(
371 ExtensibleBitmap,
372 [
373 MAP_NODE_BITS.to_le_bytes().as_slice(), ((MAP_NODE_BITS * 10) as u32).to_le_bytes().as_slice(), (2 as u32).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 2) as u32).to_le_bytes().as_slice(), ((1 << 2) as u64).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 7) as u32).to_le_bytes().as_slice(), ((1 << 7) as u64).to_le_bytes().as_slice(), ]
381 .concat(),
382 result,
383 _policy_data,
384 {
385 let (extensible_bitmap, tail) = result.expect("parse");
386 assert_eq!(36, tail.offset());
387 for i in 0..(MAP_NODE_BITS * 10) {
388 let expected = i == ((MAP_NODE_BITS * 2) + 2) || i == ((MAP_NODE_BITS * 7) + 7);
389 assert_eq!(expected, extensible_bitmap.is_set(i));
390 }
391
392 let mut count: u32 = 0;
393 for (i, bit) in extensible_bitmap.iter().enumerate() {
394 let expected = i == (((MAP_NODE_BITS * 2) + 2) as usize)
395 || i == (((MAP_NODE_BITS * 7) + 7) as usize);
396 assert_eq!(expected, bit);
397 count = count + 1;
398 }
399 assert_eq!(MAP_NODE_BITS * 10, count);
400 Some((extensible_bitmap, tail))
401 }
402 );
403 }
404
405 #[test]
406 fn extensible_bitmap_sparse_malformed() {
407 parse_test!(
408 ExtensibleBitmap,
409 [
410 (MAP_NODE_BITS - 1).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 10) as u32).to_le_bytes().as_slice(), (2 as u32).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 2) as u32).to_le_bytes().as_slice(), ((1 << 2) as u64).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 7) as u32).to_le_bytes().as_slice(), ((1 << 7) as u64).to_le_bytes().as_slice(), ]
418 .concat(),
419 result,
420 policy_data,
421 {
422 let (parsed, tail) = result.expect("parsed");
423 assert_eq!(36, tail.offset());
424 let mut context = PolicyValidationContext { data: policy_data.clone() };
425 assert_eq!(
426 Err(ValidateError::InvalidExtensibleBitmapItemSize {
427 found_size: MAP_NODE_BITS - 1
428 }),
429 parsed.validate(&mut context).map_err(as_validate_error)
430 );
431 Some((parsed, tail))
432 }
433 );
434
435 parse_test!(
436 ExtensibleBitmap,
437 [
438 MAP_NODE_BITS.to_le_bytes().as_slice(), (((MAP_NODE_BITS * 10) + 1) as u32).to_le_bytes().as_slice(), (2 as u32).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 2) as u32).to_le_bytes().as_slice(), ((1 << 2) as u64).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 7) as u32).to_le_bytes().as_slice(), ((1 << 7) as u64).to_le_bytes().as_slice(), ]
446 .concat(),
447 result,
448 policy_data,
449 {
450 let (parsed, tail) = result.expect("parsed");
451 assert_eq!(36, tail.offset());
452 let mut context = PolicyValidationContext { data: policy_data.clone() };
453 assert_eq!(
454 Err(ValidateError::MisalignedExtensibleBitmapHighBit {
455 found_size: MAP_NODE_BITS,
456 found_high_bit: (MAP_NODE_BITS * 10) + 1
457 }),
458 parsed.validate(&mut context).map_err(as_validate_error),
459 );
460 Some((parsed, tail))
461 }
462 );
463
464 parse_test!(
465 ExtensibleBitmap,
466 [
467 MAP_NODE_BITS.to_le_bytes().as_slice(), ((MAP_NODE_BITS * 10) as u32).to_le_bytes().as_slice(), (11 as u32).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 2) as u32).to_le_bytes().as_slice(), ((1 << 2) as u64).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 7) as u32).to_le_bytes().as_slice(), ((1 << 7) as u64).to_le_bytes().as_slice(), ]
475 .concat(),
476 result,
477 _policy_data,
478 {
479 match result.err().map(Into::<anyhow::Error>::into).map(as_parse_error) {
480 Some(ParseError::MissingData { type_name, type_size, num_bytes: 0 }) => {
482 assert_eq!(std::any::type_name::<MapItem>(), type_name);
483 assert_eq!(std::mem::size_of::<MapItem>(), type_size);
484 }
485 v => {
486 panic!(
487 "Expected Some({:?}), but got {:?}",
488 ParseError::MissingData {
489 type_name: std::any::type_name::<MapItem>(),
490 type_size: std::mem::size_of::<MapItem>(),
491 num_bytes: 0,
492 },
493 v
494 );
495 }
496 };
497 None::<(ExtensibleBitmap, PolicyCursor)>
498 }
499 );
500
501 parse_test!(
502 ExtensibleBitmap,
503 [
504 MAP_NODE_BITS.to_le_bytes().as_slice(), ((MAP_NODE_BITS * 10) as u32).to_le_bytes().as_slice(), (2 as u32).to_le_bytes().as_slice(), (((MAP_NODE_BITS * 2) + 1) as u32).to_le_bytes().as_slice(), ((1 << 2) as u64).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 7) as u32).to_le_bytes().as_slice(), ((1 << 7) as u64).to_le_bytes().as_slice(), ]
512 .concat(),
513 result,
514 policy_data,
515 {
516 let (parsed, tail) = result.expect("parsed");
517 assert_eq!(36, tail.offset());
518 let mut context = PolicyValidationContext { data: policy_data.clone() };
519 match parsed.validate(&mut context).map_err(as_validate_error) {
520 Err(ValidateError::MisalignedExtensibleBitmapItemStartBit {
521 found_start_bit,
522 ..
523 }) => {
524 assert_eq!((MAP_NODE_BITS * 2) + 1, found_start_bit);
525 }
526 parse_err => {
527 assert!(
528 false,
529 "Expected Err(MisalignedExtensibleBitmapItemStartBit...), but got {:?}",
530 parse_err
531 );
532 }
533 }
534 Some((parsed, tail))
535 }
536 );
537
538 parse_test!(
539 ExtensibleBitmap,
540 [
541 MAP_NODE_BITS.to_le_bytes().as_slice(), ((MAP_NODE_BITS * 10) as u32).to_le_bytes().as_slice(), (2 as u32).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 7) as u32).to_le_bytes().as_slice(), ((1 << 7) as u64).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 2) as u32).to_le_bytes().as_slice(), ((1 << 2) as u64).to_le_bytes().as_slice(), ]
549 .concat(),
550 result,
551 policy_data,
552 {
553 let (parsed, tail) = result.expect("parsed");
554 assert_eq!(36, tail.offset());
555 let mut context = PolicyValidationContext { data: policy_data.clone() };
556 assert_eq!(
557 parsed.validate(&mut context).map_err(as_validate_error),
558 Err(ValidateError::OutOfOrderExtensibleBitmapItems {
559 found_start_bit: MAP_NODE_BITS * 2,
560 min_start: (MAP_NODE_BITS * 7) + MAP_NODE_BITS,
561 })
562 );
563 Some((parsed, tail))
564 }
565 );
566
567 parse_test!(
568 ExtensibleBitmap,
569 [
570 MAP_NODE_BITS.to_le_bytes().as_slice(), ((MAP_NODE_BITS * 10) as u32).to_le_bytes().as_slice(), (3 as u32).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 2) as u32).to_le_bytes().as_slice(), ((1 << 2) as u64).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 7) as u32).to_le_bytes().as_slice(), ((1 << 7) as u64).to_le_bytes().as_slice(), ]
578 .concat(),
579 result,
580 _policy_data,
581 {
582 match result.err().map(Into::<anyhow::Error>::into).map(as_parse_error) {
583 Some(ParseError::MissingData { type_name, type_size, num_bytes: 0 }) => {
585 assert_eq!(std::any::type_name::<MapItem>(), type_name);
586 assert_eq!(std::mem::size_of::<MapItem>(), type_size);
587 }
588 parse_err => {
589 assert!(
590 false,
591 "Expected Some({:?}), but got {:?}",
592 ParseError::MissingData {
593 type_name: std::any::type_name::<MapItem>(),
594 type_size: std::mem::size_of::<MapItem>(),
595 num_bytes: 0
596 },
597 parse_err
598 );
599 }
600 };
601 None::<(ExtensibleBitmap, PolicyCursor)>
602 }
603 );
604 }
605
606 #[test]
607 fn extensible_bitmap_spans_iterator() {
608 type Span = ExtensibleBitmapSpan;
609
610 parse_test!(
612 ExtensibleBitmap,
613 [
614 MAP_NODE_BITS.to_le_bytes().as_slice(), ((MAP_NODE_BITS * 10) as u32).to_le_bytes().as_slice(), (2 as u32).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 2) as u32).to_le_bytes().as_slice(), ((1 << 2) as u64).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 7) as u32).to_le_bytes().as_slice(), ((1 << 7) | (1 << 8) as u64).to_le_bytes().as_slice(), ]
622 .concat(),
623 result,
624 _policy_data,
625 {
626 let (extensible_bitmap, tail) = result.expect("parse");
627 assert_eq!(36, tail.offset());
628
629 let mut iterator = extensible_bitmap.spans();
630 assert_eq!(
631 iterator.next(),
632 Some(Span { low: (MAP_NODE_BITS * 2) + 2, high: (MAP_NODE_BITS * 2) + 2 })
633 );
634 assert_eq!(
635 iterator.next(),
636 Some(Span { low: (MAP_NODE_BITS * 7) + 7, high: (MAP_NODE_BITS * 7) + 8 })
637 );
638 assert_eq!(iterator.next(), None);
639
640 Some((extensible_bitmap, tail))
641 }
642 );
643
644 parse_test!(
646 ExtensibleBitmap,
647 [
648 MAP_NODE_BITS.to_le_bytes().as_slice(), ((MAP_NODE_BITS * 10) as u32).to_le_bytes().as_slice(), (2 as u32).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 6) as u32).to_le_bytes().as_slice(), ((1 as u64) << 63).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 7) as u32).to_le_bytes().as_slice(), ((1 << 0) | (1 << 1) as u64).to_le_bytes().as_slice(), ]
656 .concat(),
657 result,
658 _policy_data,
659 {
660 let (extensible_bitmap, tail) = result.expect("parse");
661 assert_eq!(36, tail.offset());
662
663 let mut iterator = extensible_bitmap.spans();
664 assert_eq!(
665 iterator.next(),
666 Some(Span { low: (MAP_NODE_BITS * 6) + 63, high: (MAP_NODE_BITS * 7) + 1 })
667 );
668 assert_eq!(iterator.next(), None);
669
670 Some((extensible_bitmap, tail))
671 }
672 );
673
674 parse_test!(
677 ExtensibleBitmap,
678 [
679 MAP_NODE_BITS.to_le_bytes().as_slice(), ((MAP_NODE_BITS * 10) as u32).to_le_bytes().as_slice(), (2 as u32).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 5) as u32).to_le_bytes().as_slice(), (u64::MAX).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 7) as u32).to_le_bytes().as_slice(), (u64::MAX).to_le_bytes().as_slice(), ]
687 .concat(),
688 result,
689 _policy_data,
690 {
691 let (extensible_bitmap, tail) = result.expect("parse");
692 assert_eq!(36, tail.offset());
693
694 let mut iterator = extensible_bitmap.spans();
695 assert_eq!(
696 iterator.next(),
697 Some(Span { low: (MAP_NODE_BITS * 5), high: (MAP_NODE_BITS * 6) - 1 })
698 );
699 assert_eq!(
700 iterator.next(),
701 Some(Span { low: (MAP_NODE_BITS * 7), high: (MAP_NODE_BITS * 8) - 1 })
702 );
703 assert_eq!(iterator.next(), None);
704
705 Some((extensible_bitmap, tail))
706 }
707 );
708
709 parse_test!(
711 ExtensibleBitmap,
712 [
713 MAP_NODE_BITS.to_le_bytes().as_slice(), ((MAP_NODE_BITS * 10) as u32).to_le_bytes().as_slice(), (1 as u32).to_le_bytes().as_slice(), ((MAP_NODE_BITS * 9) as u32).to_le_bytes().as_slice(), (u64::MAX).to_le_bytes().as_slice(), ]
719 .concat(),
720 result,
721 _policy_data,
722 {
723 let (extensible_bitmap, tail) = result.expect("parse");
724 assert_eq!(24, tail.offset());
725
726 let mut iterator = extensible_bitmap.spans();
727 assert_eq!(
728 iterator.next(),
729 Some(Span { low: (MAP_NODE_BITS * 9), high: (MAP_NODE_BITS * 10) - 1 })
730 );
731 assert_eq!(iterator.next(), None);
732
733 Some((extensible_bitmap, tail))
734 }
735 );
736 }
737}