Skip to content

Commit 147f41f

Browse files
authored
der: have SetOf(Vec)::insert check for duplicates (#2217)
Previously they would detect duplicates at sorting time, which would both leave the set not completely sorted, and containing duplicates, both of which are disallowed. This adds an eager initial check the given item is not a duplicate prior to the actual state mutation. Closes #2123
1 parent a0bc127 commit 147f41f

File tree

1 file changed

+54
-5
lines changed

1 file changed

+54
-5
lines changed

der/src/asn1/set_of.rs

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,23 +46,22 @@ where
4646

4747
/// Add an item to this [`SetOf`].
4848
///
49-
/// Items MUST be added in lexicographical order according to the
50-
/// [`DerOrd`] impl on `T`.
49+
/// Items MUST be added in lexicographical order according to the [`DerOrd`] impl on `T`.
5150
#[deprecated(since = "0.7.6", note = "use `insert` or `insert_ordered` instead")]
5251
pub fn add(&mut self, new_elem: T) -> Result<(), Error> {
5352
self.insert_ordered(new_elem)
5453
}
5554

5655
/// Insert an item into this [`SetOf`].
5756
pub fn insert(&mut self, item: T) -> Result<(), Error> {
57+
check_duplicate(&item, self.iter())?;
5858
self.inner.push(item)?;
5959
der_sort(self.inner.as_mut())
6060
}
6161

6262
/// Insert an item into this [`SetOf`].
6363
///
64-
/// Items MUST be added in lexicographical order according to the
65-
/// [`DerOrd`] impl on `T`.
64+
/// Items MUST be added in lexicographical order according to the [`DerOrd`] impl on `T`.
6665
pub fn insert_ordered(&mut self, item: T) -> Result<(), Error> {
6766
// Ensure set elements are lexicographically ordered
6867
if let Some(last) = self.inner.last() {
@@ -266,6 +265,7 @@ where
266265

267266
/// Insert an item into this [`SetOfVec`]. Must be unique.
268267
pub fn insert(&mut self, item: T) -> Result<(), Error> {
268+
check_duplicate(&item, self.iter())?;
269269
self.inner.push(item);
270270
der_sort(&mut self.inner)
271271
}
@@ -417,7 +417,7 @@ where
417417
}
418418
}
419419

420-
// Implement by hand because the derive would create invalid values.
420+
// Implement by hand because custom derive would create invalid values.
421421
// Use the conversion from Vec to create a valid value.
422422
#[cfg(feature = "arbitrary")]
423423
impl<'a, T> arbitrary::Arbitrary<'a> for SetOfVec<T>
@@ -434,6 +434,24 @@ where
434434
}
435435
}
436436

437+
/// Check if the given item is a duplicate, given an iterator over sorted items (which we can
438+
/// short-circuit once we hit `Ordering::Less`.
439+
fn check_duplicate<'a, T, I>(item: &T, iter: I) -> Result<(), Error>
440+
where
441+
T: DerOrd + 'a,
442+
I: Iterator<Item = &'a T>,
443+
{
444+
for item2 in iter {
445+
match item.der_cmp(item2)? {
446+
Ordering::Less => return Ok(()), // all remaining items are greater
447+
Ordering::Equal => return Err(ErrorKind::SetDuplicate.into()),
448+
Ordering::Greater => continue,
449+
}
450+
}
451+
452+
Ok(())
453+
}
454+
437455
/// Ensure set elements are lexicographically ordered using [`DerOrd`].
438456
fn check_der_ordering<T: DerOrd>(a: &T, b: &T) -> Result<(), Error> {
439457
match a.der_cmp(b)? {
@@ -480,6 +498,21 @@ mod tests {
480498
use super::SetOfVec;
481499
use crate::{DerOrd, ErrorKind};
482500

501+
#[test]
502+
fn setof_insert() {
503+
let mut setof = SetOf::<u8, 10>::new();
504+
setof.insert(42).unwrap();
505+
assert_eq!(setof.len(), 1);
506+
assert_eq!(*setof.iter().next().unwrap(), 42);
507+
508+
// Ensure duplicates are disallowed
509+
assert_eq!(
510+
setof.insert(42).unwrap_err().kind(),
511+
ErrorKind::SetDuplicate
512+
);
513+
assert_eq!(setof.len(), 1);
514+
}
515+
483516
#[test]
484517
fn setof_tryfrom_array() {
485518
let arr = [3u16, 2, 1, 65535, 0];
@@ -505,6 +538,22 @@ mod tests {
505538
assert_eq!(set1.der_cmp(&set2), Ok(Ordering::Greater));
506539
}
507540

541+
#[cfg(feature = "alloc")]
542+
#[test]
543+
fn setofvec_insert() {
544+
let mut setof = SetOfVec::new();
545+
setof.insert(42).unwrap();
546+
assert_eq!(setof.len(), 1);
547+
assert_eq!(*setof.iter().next().unwrap(), 42);
548+
549+
// Ensure duplicates are disallowed
550+
assert_eq!(
551+
setof.insert(42).unwrap_err().kind(),
552+
ErrorKind::SetDuplicate
553+
);
554+
assert_eq!(setof.len(), 1);
555+
}
556+
508557
#[cfg(feature = "alloc")]
509558
#[test]
510559
fn setofvec_tryfrom_array() {

0 commit comments

Comments
 (0)