Skip to content

Commit 8f480f5

Browse files
authored
der: add SetOf(Vec)::insert(_ordered); deprecate add (#1067)
Renames the insertion methods on `SetOf` and `SetOfVec` from `add` to `insert_ordered`, deprecating the previous `add` method. Also adds an `insert` method which pushes onto the underlying `(Array)Vec` then calls `der_sort`. This should be relatively fast since the underlying algorithm is insertion sort and operating on data which is mostly in-order. The name `insert` is more consistent with `BTreeSet`/`HashSet`.
1 parent 57b6ca5 commit 8f480f5

File tree

11 files changed

+84
-52
lines changed

11 files changed

+84
-52
lines changed

.github/workflows/pkcs7.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,6 @@ jobs:
4040
- uses: RustCrypto/actions/cargo-hack-install@master
4141
- run: cargo hack build --target ${{ matrix.target }} --feature-powerset
4242

43-
minimal-versions:
44-
uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master
45-
with:
46-
working-directory: ${{ github.workflow }}
47-
4843
test:
4944
runs-on: ubuntu-latest
5045
strategy:

.github/workflows/x509-cert.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,12 @@ jobs:
4040
- uses: RustCrypto/actions/cargo-hack-install@master
4141
- run: cargo hack build --target ${{ matrix.target }} --feature-powerset --exclude-features arbitrary,builder,default,std
4242

43-
minimal-versions:
44-
uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master
45-
with:
46-
working-directory: ${{ github.workflow }}
47-
install-zlint: true
43+
# TODO(tarcieri): re-enable after next `der` release
44+
# minimal-versions:
45+
# uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master
46+
# with:
47+
# working-directory: ${{ github.workflow }}
48+
# install-zlint: true
4849

4950
test:
5051
runs-on: ubuntu-latest

cms/src/content_info.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ impl TryFrom<Certificate> for ContentInfo {
6161

6262
fn try_from(cert: Certificate) -> der::Result<Self> {
6363
let mut certs = CertificateSet(Default::default());
64-
certs.0.add(CertificateChoices::Certificate(cert))?;
64+
certs.0.insert(CertificateChoices::Certificate(cert))?;
6565

6666
// include empty CRLs field instead of omitting it to match OpenSSL's behavior
6767
let sd = SignedData {
@@ -93,7 +93,7 @@ impl TryFrom<PkiPath> for ContentInfo {
9393
fn try_from(pki_path: PkiPath) -> der::Result<Self> {
9494
let mut certs = CertificateSet(Default::default());
9595
for cert in pki_path {
96-
certs.0.add(CertificateChoices::Certificate(cert))?;
96+
certs.0.insert(CertificateChoices::Certificate(cert))?;
9797
}
9898

9999
// include empty CRLs field instead of omitting it to match OpenSSL's behavior

der/src/arrayvec.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,11 @@ impl<T, const N: usize> ArrayVec<T, N> {
2323
}
2424
}
2525

26-
/// Add an element to this [`ArrayVec`].
27-
///
28-
/// Items MUST be added in lexicographical order according to the `Ord`
29-
/// impl on `T`.
30-
pub fn add(&mut self, element: T) -> Result<()> {
26+
/// Push an item into this [`ArrayVec`].
27+
pub fn push(&mut self, item: T) -> Result<()> {
3128
match self.length.checked_add(1) {
3229
Some(n) if n <= N => {
33-
self.elements[self.length] = Some(element);
30+
self.elements[self.length] = Some(item);
3431
self.length = n;
3532
Ok(())
3633
}
@@ -138,11 +135,11 @@ mod tests {
138135
#[test]
139136
fn add() {
140137
let mut vec = ArrayVec::<u8, 3>::new();
141-
vec.add(1).unwrap();
142-
vec.add(2).unwrap();
143-
vec.add(3).unwrap();
138+
vec.push(1).unwrap();
139+
vec.push(2).unwrap();
140+
vec.push(3).unwrap();
144141

145-
assert_eq!(vec.add(4).err().unwrap(), ErrorKind::Overlength.into());
142+
assert_eq!(vec.push(4).err().unwrap(), ErrorKind::Overlength.into());
146143
assert_eq!(vec.len(), 3);
147144
}
148145
}

der/src/asn1/sequence_of.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl<T, const N: usize> SequenceOf<T, N> {
3030

3131
/// Add an element to this [`SequenceOf`].
3232
pub fn add(&mut self, element: T) -> Result<()> {
33-
self.inner.add(element)
33+
self.inner.push(element)
3434
}
3535

3636
/// Get an element of this [`SequenceOf`].

der/src/asn1/set_of.rs

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,32 @@ where
4444
}
4545
}
4646

47-
/// Add an element to this [`SetOf`].
47+
/// Add an item to this [`SetOf`].
4848
///
4949
/// Items MUST be added in lexicographical order according to the
5050
/// [`DerOrd`] impl on `T`.
51+
#[deprecated(since = "0.7.6", note = "use `insert` or `insert_ordered` instead")]
5152
pub fn add(&mut self, new_elem: T) -> Result<()> {
53+
self.insert_ordered(new_elem)
54+
}
55+
56+
/// Insert an item into this [`SetOf`].
57+
pub fn insert(&mut self, item: T) -> Result<()> {
58+
self.inner.push(item)?;
59+
der_sort(self.inner.as_mut())
60+
}
61+
62+
/// Insert an item into this [`SetOf`].
63+
///
64+
/// Items MUST be added in lexicographical order according to the
65+
/// [`DerOrd`] impl on `T`.
66+
pub fn insert_ordered(&mut self, item: T) -> Result<()> {
5267
// Ensure set elements are lexicographically ordered
53-
if let Some(last_elem) = self.inner.last() {
54-
match new_elem.der_cmp(last_elem)? {
55-
Ordering::Less => return Err(ErrorKind::SetOrdering.into()),
56-
Ordering::Equal => return Err(ErrorKind::SetDuplicate.into()),
57-
Ordering::Greater => (),
58-
}
68+
if let Some(last) = self.inner.last() {
69+
check_der_ordering(last, &item)?;
5970
}
6071

61-
self.inner.add(new_elem)
72+
self.inner.push(item)
6273
}
6374

6475
/// Get the nth element from this [`SetOf`].
@@ -102,7 +113,7 @@ where
102113
let mut result = Self::new();
103114

104115
while !reader.is_finished() {
105-
result.inner.add(T::decode(reader)?)?;
116+
result.inner.push(T::decode(reader)?)?;
106117
}
107118

108119
der_sort(result.inner.as_mut())?;
@@ -149,7 +160,7 @@ where
149160
let mut result = SetOf::new();
150161

151162
for elem in arr {
152-
result.add(elem)?;
163+
result.insert_ordered(elem)?;
153164
}
154165

155166
Ok(result)
@@ -232,16 +243,9 @@ where
232243
///
233244
/// Items MUST be added in lexicographical order according to the
234245
/// [`DerOrd`] impl on `T`.
235-
pub fn add(&mut self, new_elem: T) -> Result<()> {
236-
// Ensure set elements are lexicographically ordered
237-
if let Some(last_elem) = self.inner.last() {
238-
if new_elem.der_cmp(last_elem)? != Ordering::Greater {
239-
return Err(ErrorKind::SetOrdering.into());
240-
}
241-
}
242-
243-
self.inner.push(new_elem);
244-
Ok(())
246+
#[deprecated(since = "0.7.6", note = "use `insert` or `insert_ordered` instead")]
247+
pub fn add(&mut self, item: T) -> Result<()> {
248+
self.insert_ordered(item)
245249
}
246250

247251
/// Extend a [`SetOfVec`] using an iterator.
@@ -256,6 +260,26 @@ where
256260
der_sort(&mut self.inner)
257261
}
258262

263+
/// Insert an item into this [`SetOfVec`]. Must be unique.
264+
pub fn insert(&mut self, item: T) -> Result<()> {
265+
self.inner.push(item);
266+
der_sort(&mut self.inner)
267+
}
268+
269+
/// Insert an item into this [`SetOfVec`]. Must be unique.
270+
///
271+
/// Items MUST be added in lexicographical order according to the
272+
/// [`DerOrd`] impl on `T`.
273+
pub fn insert_ordered(&mut self, item: T) -> Result<()> {
274+
// Ensure set elements are lexicographically ordered
275+
if let Some(last) = self.inner.last() {
276+
check_der_ordering(last, &item)?;
277+
}
278+
279+
self.inner.push(item);
280+
Ok(())
281+
}
282+
259283
/// Borrow the elements of this [`SetOfVec`] as a slice.
260284
pub fn as_slice(&self) -> &[T] {
261285
self.inner.as_slice()
@@ -409,6 +433,15 @@ where
409433
}
410434
}
411435

436+
/// Ensure set elements are lexicographically ordered using [`DerOrd`].
437+
fn check_der_ordering<T: DerOrd>(a: &T, b: &T) -> Result<()> {
438+
match a.der_cmp(b)? {
439+
Ordering::Less => Ok(()),
440+
Ordering::Equal => Err(ErrorKind::SetDuplicate.into()),
441+
Ordering::Greater => Err(ErrorKind::SetOrdering.into()),
442+
}
443+
}
444+
412445
/// Sort a mut slice according to its [`DerOrd`], returning any errors which
413446
/// might occur during the comparison.
414447
///

pkcs7/tests/content_tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ fn create_pkcs7_signed_data() {
207207
parameters: None,
208208
};
209209
let mut digest_algorithms = DigestAlgorithmIdentifiers::new();
210-
digest_algorithms.add(digest_algorithm).unwrap();
210+
digest_algorithms.insert(digest_algorithm).unwrap();
211211
digest_algorithms
212212
};
213213

@@ -223,7 +223,7 @@ fn create_pkcs7_signed_data() {
223223
let cert: x509_cert::Certificate = x509_cert::Certificate::from_pem(cert_pem).unwrap();
224224
let cert_choice = CertificateChoices::Certificate(cert);
225225
let mut certs = CertificateSet::new();
226-
certs.add(cert_choice).unwrap();
226+
certs.insert(cert_choice).unwrap();
227227
Some(certs)
228228
};
229229

x509-cert/fuzz/Cargo.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,14 @@ cargo-fuzz = true
1010

1111
[dependencies]
1212
libfuzzer-sys = "0.4"
13-
x509-cert = { path = ".." }
13+
x509-cert = "*"
1414

1515
# Prevents this crate from interfering with the workspace
1616
[workspace]
1717
members = ["."]
18+
19+
[patch.crates-io]
20+
der = { path = "../../der" }
21+
der_derive = { path = "../../der/derive" }
22+
pem-rfc7468 = { path = "../../pem-rfc7468" }
23+
spki = { path = "../../spki" }

x509-cert/src/builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ where
501501
fn finalize(&mut self) -> der::Result<vec::Vec<u8>> {
502502
self.info
503503
.attributes
504-
.add(self.extension_req.clone().try_into()?)?;
504+
.insert(self.extension_req.clone().try_into()?)?;
505505

506506
self.info.to_der()
507507
}

x509-cert/src/request.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ impl TryFrom<ExtensionReq> for Attribute {
117117

118118
fn try_from(extension_req: ExtensionReq) -> der::Result<Attribute> {
119119
let mut values: SetOfVec<AttributeValue> = Default::default();
120-
values.add(Any::encode_from(&extension_req.0)?)?;
120+
values.insert(Any::encode_from(&extension_req.0)?)?;
121121

122122
Ok(Attribute {
123123
oid: ExtensionReq::OID,

x509-cert/tests/name.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,18 +122,18 @@ fn decode_rdn() {
122122
assert_eq!(utf8a.to_string(), "JOHN SMITH");
123123

124124
let mut from_scratch = RelativeDistinguishedName::default();
125-
assert!(from_scratch.0.add(atav1a.clone()).is_ok());
126-
assert!(from_scratch.0.add(atav2a.clone()).is_ok());
125+
assert!(from_scratch.0.insert(atav1a.clone()).is_ok());
126+
assert!(from_scratch.0.insert(atav2a.clone()).is_ok());
127127
let reencoded = from_scratch.to_der().unwrap();
128128
assert_eq!(
129129
reencoded,
130130
&hex!("311F300A060355040A0C03313233301106035504030C0A4A4F484E20534D495448")
131131
);
132132

133133
let mut from_scratch2 = RelativeDistinguishedName::default();
134-
assert!(from_scratch2.0.add(atav2a.clone()).is_ok());
134+
assert!(from_scratch2.0.insert_ordered(atav2a.clone()).is_ok());
135135
// fails when caller adds items not in DER lexicographical order
136-
assert!(from_scratch2.0.add(atav1a.clone()).is_err());
136+
assert!(from_scratch2.0.insert_ordered(atav1a.clone()).is_err());
137137

138138
// allow out-of-order RDNs (see: RustCrypto/formats#625)
139139
assert!(RelativeDistinguishedName::from_der(

0 commit comments

Comments
 (0)