use crate::{
metadata::{
customattributes::{
encode_custom_attribute_value, CustomAttributeArgument, CustomAttributeValue,
},
tables::{
CodedIndex, CodedIndexType, CustomAttributeRaw, DeclSecurityRaw, TableDataOwned,
TableId,
},
token::Token,
},
test::{create_test_assembly, get_testfile_mscorlib, TestAssembly},
Error, Result,
};
pub fn owned_security_validator_file_factory() -> Result<Vec<TestAssembly>> {
let mut assemblies = Vec::new();
let Some(clean_testfile) = get_testfile_mscorlib() else {
return Err(Error::Other(
"mscorlib.dll not available - test cannot run".to_string(),
));
};
assemblies.push(TestAssembly::new(&clean_testfile, true));
assemblies.push(create_assembly_with_invalid_security_action()?);
assemblies.push(create_assembly_with_malformed_permission_set()?);
assemblies.push(create_assembly_with_conflicting_security_attributes()?);
assemblies.push(create_assembly_with_security_transparency_violations()?);
Ok(assemblies)
}
pub fn create_assembly_with_invalid_security_action() -> Result<TestAssembly> {
create_test_assembly(get_testfile_mscorlib, |assembly| {
let invalid_declsecurity = DeclSecurityRaw {
rid: 1,
token: Token::new(0x0E000001),
offset: 0,
action: 99, parent: CodedIndex::new(TableId::TypeDef, 1, CodedIndexType::HasDeclSecurity),
permission_set: 1, };
assembly.table_row_add(
TableId::DeclSecurity,
TableDataOwned::DeclSecurity(invalid_declsecurity),
)?;
Ok(())
})
}
pub fn create_assembly_with_malformed_permission_set() -> Result<TestAssembly> {
create_test_assembly(get_testfile_mscorlib, |assembly| {
let malformed_xml = b"<InvalidRoot><Permission>SomePermission</Permission></InvalidRoot>";
let blob_index = assembly.blob_add(malformed_xml)?;
let declsecurity_with_bad_xml = DeclSecurityRaw {
rid: 1,
token: Token::new(0x0E000001),
offset: 0,
action: 3, parent: CodedIndex::new(TableId::TypeDef, 1, CodedIndexType::HasDeclSecurity),
permission_set: blob_index.placeholder(),
};
assembly.table_row_add(
TableId::DeclSecurity,
TableDataOwned::DeclSecurity(declsecurity_with_bad_xml),
)?;
Ok(())
})
}
pub fn create_assembly_with_conflicting_security_attributes() -> Result<TestAssembly> {
create_test_assembly(get_testfile_mscorlib, |assembly| {
let critical_attr_value = CustomAttributeValue {
fixed_args: vec![CustomAttributeArgument::String(
"SecurityCritical".to_string(),
)],
named_args: vec![],
};
let critical_blob = encode_custom_attribute_value(&critical_attr_value).map_err(|e| {
Error::Other(format!("Failed to encode SecurityCritical attribute: {e}"))
})?;
let critical_blob_index = assembly.blob_add(&critical_blob)?;
let next_rid = assembly.original_table_row_count(TableId::CustomAttribute) + 1;
let critical_custom_attr = CustomAttributeRaw {
rid: next_rid,
token: Token::new(0x0C000000 + next_rid),
offset: 0,
parent: CodedIndex::new(TableId::TypeDef, 2, CodedIndexType::HasCustomAttribute),
constructor: CodedIndex::new(
TableId::MethodDef,
1,
CodedIndexType::CustomAttributeType,
),
value: critical_blob_index.placeholder(),
};
assembly.table_row_add(
TableId::CustomAttribute,
TableDataOwned::CustomAttribute(critical_custom_attr),
)?;
let transparent_attr_value = CustomAttributeValue {
fixed_args: vec![CustomAttributeArgument::String(
"SecurityTransparent".to_string(),
)],
named_args: vec![],
};
let transparent_blob =
encode_custom_attribute_value(&transparent_attr_value).map_err(|e| {
Error::Other(format!(
"Failed to encode SecurityTransparent attribute: {e}"
))
})?;
let transparent_blob_index = assembly.blob_add(&transparent_blob)?;
let next_rid2 = assembly.original_table_row_count(TableId::CustomAttribute) + 2;
let transparent_custom_attr = CustomAttributeRaw {
rid: next_rid2,
token: Token::new(0x0C000000 + next_rid2),
offset: 0,
parent: CodedIndex::new(TableId::TypeDef, 2, CodedIndexType::HasCustomAttribute),
constructor: CodedIndex::new(
TableId::MethodDef,
1,
CodedIndexType::CustomAttributeType,
),
value: transparent_blob_index.placeholder(),
};
assembly.table_row_add(
TableId::CustomAttribute,
TableDataOwned::CustomAttribute(transparent_custom_attr),
)?;
Ok(())
})
}
pub fn create_assembly_with_security_transparency_violations() -> Result<TestAssembly> {
create_test_assembly(get_testfile_mscorlib, |assembly| {
let critical_attr_value = CustomAttributeValue {
fixed_args: vec![CustomAttributeArgument::String(
"SecurityCritical".to_string(),
)],
named_args: vec![],
};
let critical_blob = encode_custom_attribute_value(&critical_attr_value).map_err(|e| {
Error::Other(format!("Failed to encode SecurityCritical attribute: {e}"))
})?;
let critical_blob_index = assembly.blob_add(&critical_blob)?;
let next_rid = assembly.original_table_row_count(TableId::CustomAttribute) + 1;
let critical_custom_attr = CustomAttributeRaw {
rid: next_rid,
token: Token::new(0x0C000000 + next_rid),
offset: 0,
parent: CodedIndex::new(TableId::TypeDef, 2, CodedIndexType::HasCustomAttribute),
constructor: CodedIndex::new(
TableId::MethodDef,
1,
CodedIndexType::CustomAttributeType,
),
value: critical_blob_index.placeholder(),
};
assembly.table_row_add(
TableId::CustomAttribute,
TableDataOwned::CustomAttribute(critical_custom_attr),
)?;
let transparent_attr_value = CustomAttributeValue {
fixed_args: vec![CustomAttributeArgument::String(
"SecurityTransparent".to_string(),
)],
named_args: vec![],
};
let transparent_blob =
encode_custom_attribute_value(&transparent_attr_value).map_err(|e| {
Error::Other(format!(
"Failed to encode SecurityTransparent attribute: {e}"
))
})?;
let transparent_blob_index = assembly.blob_add(&transparent_blob)?;
let next_rid2 = assembly.original_table_row_count(TableId::CustomAttribute) + 2;
let transparent_custom_attr = CustomAttributeRaw {
rid: next_rid2,
token: Token::new(0x0C000000 + next_rid2),
offset: 0,
parent: CodedIndex::new(TableId::TypeDef, 3, CodedIndexType::HasCustomAttribute),
constructor: CodedIndex::new(
TableId::MethodDef,
1,
CodedIndexType::CustomAttributeType,
),
value: transparent_blob_index.placeholder(),
};
assembly.table_row_add(
TableId::CustomAttribute,
TableDataOwned::CustomAttribute(transparent_custom_attr),
)?;
Ok(())
})
}