use std::sync::Arc;
use structured_asn1::memory::{Memory, MemoryAccount};
use structured_asn1::{Encoding, Limits, Parser};
fn memory() -> Memory {
Memory::new(Arc::new(MemoryAccount::new(65536, 65536)))
}
#[test]
fn retained_segmented_name_query_keeps_current_element_ceiling() {
let segmented = [
0x30, 14, 0x31, 12, 0x30, 10, 6, 3, 0x55, 4, 3, 0x2c, 3, 4, 1, b'a',
];
let primitive = [0x30, 12, 0x31, 10, 0x30, 8, 6, 3, 0x55, 4, 3, 12, 1, b'A'];
let left_parser = Parser::ber(memory());
let right_parser = Parser::der(memory());
let left = {
let mut reader = left_parser.read(&segmented, 400).unwrap();
let element = reader.next_element().unwrap().unwrap();
structured_pkix::name::read(&reader, &element, "subject").unwrap()
};
let right = {
let mut reader = right_parser.read(&primitive, 800).unwrap();
let element = reader.next_element().unwrap().unwrap();
structured_pkix::name::read(&reader, &element, "issuer").unwrap()
};
let funded = memory();
assert!(left.matches(&right, &funded).unwrap());
assert_eq!(funded.used(), 0);
let current = memory();
let parser = Parser::new(
Encoding::Ber,
Limits {
max_elements: 0,
..Limits::default()
},
current.clone(),
);
let reader = parser.read(&[], 900).unwrap();
let error = left
.matches(&right, &reader.execution())
.expect_err("a fresh retained source cannot bypass the current query element ceiling");
assert!(error.is_resource());
assert_eq!(error.offset(), 411);
drop(reader);
assert_eq!(current.used(), 0);
}
#[test]
fn issuer_name_storage_cannot_use_aggregate_slack_past_local_work() {
let encoded = [0x30, 9, 0x31, 7, 0x30, 5, 6, 1, 42, 5, 0];
let sufficient = memory();
let parser = Parser::der(sufficient.clone());
let mut reader = parser.read(&encoded, 400).unwrap();
let element = reader.next_element().unwrap().unwrap();
let name = structured_pkix::name::read(&reader, &element, "signerInfo.sid").unwrap();
let full_work = u64::try_from(sufficient.work_used()).unwrap();
drop(name);
drop(reader);
assert_eq!(sufficient.used(), 0);
let limited = memory();
let parser = Parser::new(
Encoding::Der,
Limits {
max_work: full_work - 1,
..Limits::default()
},
limited.clone(),
);
let mut reader = parser.read(&encoded, 400).unwrap();
let element = reader.next_element().unwrap().unwrap();
let error = structured_pkix::name::read(&reader, &element, "signerInfo.sid")
.expect_err("all catalogue allocation work belongs to this producing session");
assert!(error.is_resource());
assert_eq!(error.field(), "signerInfo.sid");
drop(reader);
assert_eq!(limited.used(), 0);
assert!(u64::try_from(limited.work_used()).unwrap() < full_work);
}
#[test]
fn repeated_rdns_cannot_bypass_the_producing_catalogue_allowance() {
let mut encoded = vec![0x30, 0x82, 3, 0];
for _ in 0..64 {
encoded.extend_from_slice(&[0x31, 10, 0x30, 8, 6, 3, 0x55, 4, 3, 12, 1, b'a']);
}
assert_eq!(encoded.len(), 772);
let memory = Memory::new(Arc::new(MemoryAccount::new(100_000_000, 100_000_000)));
let parser = Parser::new(
Encoding::Der,
Limits {
max_work: 8000,
..Limits::default()
},
memory.clone(),
);
let mut reader = parser.read(&encoded, 400).unwrap();
let element = reader.next_element().unwrap().unwrap();
let error = structured_pkix::name::read(&reader, &element, "subject")
.expect_err("RDN storage must use the producing local allowance");
assert!(error.is_resource());
assert_eq!(error.field(), "subject");
assert!(error.offset() >= 400);
assert!(memory.work_used() <= 8000);
assert_eq!(memory.used(), 0);
}
#[test]
fn decoded_name_storage_survives_reader_and_releases_with_the_result() {
let encoded = [0x30, 9, 0x31, 7, 0x30, 5, 6, 1, 42, 5, 0];
let memory = memory();
let parser = Parser::der(memory.clone());
let name;
{
let mut reader = parser.read(&encoded, 400).unwrap();
let element = reader.next_element().unwrap().unwrap();
name = structured_pkix::name::read(&reader, &element, "subject").unwrap();
}
assert!(memory.used() > 0);
assert_eq!(name.as_bytes(), &encoded);
drop(name);
assert_eq!(memory.used(), 0);
}