use crate::{
metadata::{
tables::{
CodedIndex, CodedIndexType, FieldAttributes, FieldBuilder, FieldRaw, MethodDefRaw,
NestedClassRaw, TableDataOwned, TableId, TypeAttributes, TypeDefBuilder, TypeDefRaw,
},
token::Token,
},
test::{create_test_assembly, get_testfile_crafted2, TestAssembly},
Error, Result,
};
pub fn owned_accessibility_validator_file_factory() -> Result<Vec<TestAssembly>> {
let mut assemblies = Vec::new();
let Some(clean_testfile) = get_testfile_crafted2() else {
return Err(Error::Other(
"crafted_2.exe not available - test cannot run".to_string(),
));
};
assemblies.push(TestAssembly::new(&clean_testfile, true));
assemblies.push(create_assembly_with_sealed_interface()?);
assemblies.push(create_assembly_with_interface_instance_field()?);
assemblies.push(create_assembly_with_interface_non_constant_field()?);
assemblies.push(create_assembly_with_empty_method_name()?);
assemblies.push(create_assembly_with_literal_non_static_field()?);
assemblies.push(create_assembly_with_nested_accessibility_violation()?);
Ok(assemblies)
}
pub fn create_assembly_with_sealed_interface() -> Result<TestAssembly> {
create_test_assembly(get_testfile_crafted2, |assembly| {
let name_index = assembly.string_add("InvalidSealedInterface")?;
let next_rid = assembly.original_table_row_count(TableId::TypeDef) + 1;
let invalid_interface = TypeDefRaw {
rid: next_rid,
token: Token::new(0x02000000 + next_rid),
offset: 0,
flags: TypeAttributes::INTERFACE | 0x0100, type_name: name_index.placeholder(),
type_namespace: 0,
extends: CodedIndex::new(TableId::TypeRef, 1, CodedIndexType::TypeDefOrRef),
field_list: 1,
method_list: 1,
};
assembly.table_row_add(TableId::TypeDef, TableDataOwned::TypeDef(invalid_interface))?;
Ok(())
})
}
pub fn create_assembly_with_interface_instance_field() -> Result<TestAssembly> {
create_test_assembly(get_testfile_crafted2, |assembly| {
let interface_rid = assembly.original_table_row_count(TableId::TypeDef) + 1;
let field_rid = assembly.original_table_row_count(TableId::Field) + 1;
let interface_name_index = assembly.string_add("InterfaceWithInstanceField")?;
let field_name_index = assembly.string_add("InstanceField")?;
let signature_bytes = vec![0x06, 0x08]; let signature_index = assembly.blob_add(&signature_bytes)?;
let interface_type = TypeDefRaw {
rid: interface_rid,
token: Token::new(0x02000000 + interface_rid),
offset: 0,
flags: TypeAttributes::INTERFACE | TypeAttributes::PUBLIC,
type_name: interface_name_index.placeholder(),
type_namespace: 0,
extends: CodedIndex::new(TableId::TypeRef, 1, CodedIndexType::TypeDefOrRef),
field_list: field_rid, method_list: 1,
};
let invalid_field = FieldRaw {
rid: field_rid,
token: Token::new(0x04000000 + field_rid),
offset: 0,
flags: FieldAttributes::PUBLIC, name: field_name_index.placeholder(),
signature: signature_index.placeholder(),
};
assembly.table_row_add(TableId::TypeDef, TableDataOwned::TypeDef(interface_type))?;
assembly.table_row_add(TableId::Field, TableDataOwned::Field(invalid_field))?;
Ok(())
})
}
pub fn create_assembly_with_interface_non_constant_field() -> Result<TestAssembly> {
create_test_assembly(get_testfile_crafted2, |assembly| {
let signature_bytes = vec![0x06, 0x08]; let field_token = FieldBuilder::new()
.name("NonConstantField")
.flags(FieldAttributes::PUBLIC | FieldAttributes::STATIC) .signature(&signature_bytes)
.build(assembly)?;
let _interface_token = TypeDefBuilder::new()
.name("InterfaceWithNonConstantField")
.namespace("")
.flags(TypeAttributes::INTERFACE | TypeAttributes::PUBLIC)
.field_list(
field_token
.token()
.expect("Field token should be resolved")
.row(),
) .build(assembly)?;
Ok(())
})
}
pub fn create_assembly_with_empty_method_name() -> Result<TestAssembly> {
create_test_assembly(get_testfile_crafted2, |assembly| {
let type_name_index = assembly.string_add("TypeWithEmptyMethodName")?;
let type_rid = assembly.original_table_row_count(TableId::TypeDef) + 1;
let method_rid = assembly.original_table_row_count(TableId::MethodDef) + 1;
let type_def = TypeDefRaw {
rid: type_rid,
token: Token::new(0x02000000 + type_rid),
offset: 0,
flags: TypeAttributes::PUBLIC,
type_name: type_name_index.placeholder(),
type_namespace: 0,
extends: CodedIndex::new(TableId::TypeRef, 1, CodedIndexType::TypeDefOrRef),
field_list: 1,
method_list: method_rid,
};
let empty_name_index = assembly.string_add("")?;
let signature_bytes = vec![0x00, 0x00, 0x01]; let signature_index = assembly.blob_add(&signature_bytes)?;
let invalid_method = MethodDefRaw {
rid: method_rid,
token: Token::new(0x06000000 + method_rid),
offset: 0,
rva: 0,
impl_flags: 0,
flags: 0x0006, name: empty_name_index.placeholder(), signature: signature_index.placeholder(),
param_list: 1,
};
assembly.table_row_add(TableId::TypeDef, TableDataOwned::TypeDef(type_def))?;
assembly.table_row_add(
TableId::MethodDef,
TableDataOwned::MethodDef(invalid_method),
)?;
Ok(())
})
}
pub fn create_assembly_with_literal_non_static_field() -> Result<TestAssembly> {
create_test_assembly(get_testfile_crafted2, |assembly| {
let signature_bytes = vec![0x06, 0x08]; let field_token = FieldBuilder::new()
.name("LiteralInstanceField")
.flags(FieldAttributes::PUBLIC | 0x0040) .signature(&signature_bytes)
.build(assembly)?;
let _type_token = TypeDefBuilder::new()
.name("TypeWithLiteralInstanceField")
.namespace("")
.flags(TypeAttributes::PUBLIC)
.field_list(
field_token
.token()
.expect("Field token should be resolved")
.row(),
) .build(assembly)?;
Ok(())
})
}
pub fn create_assembly_with_nested_accessibility_violation() -> Result<TestAssembly> {
create_test_assembly(get_testfile_crafted2, |assembly| {
let container_name_index = assembly.string_add("InternalContainer")?;
let container_rid = assembly.original_table_row_count(TableId::TypeDef) + 1;
let container_type = TypeDefRaw {
rid: container_rid,
token: Token::new(0x02000000 + container_rid),
offset: 0,
flags: TypeAttributes::NOT_PUBLIC, type_name: container_name_index.placeholder(),
type_namespace: 0,
extends: CodedIndex::new(TableId::TypeRef, 1, CodedIndexType::TypeDefOrRef),
field_list: 1,
method_list: 1,
};
assembly.table_row_add(TableId::TypeDef, TableDataOwned::TypeDef(container_type))?;
let nested_name_index = assembly.string_add("InternalContainer+InvalidNested")?;
let nested_rid = assembly.original_table_row_count(TableId::TypeDef) + 1;
let nested_type = TypeDefRaw {
rid: nested_rid,
token: Token::new(0x02000000 + nested_rid),
offset: 0,
flags: TypeAttributes::PUBLIC, type_name: nested_name_index.placeholder(),
type_namespace: 0,
extends: CodedIndex::new(TableId::TypeRef, 1, CodedIndexType::TypeDefOrRef),
field_list: 1,
method_list: 1,
};
assembly.table_row_add(TableId::TypeDef, TableDataOwned::TypeDef(nested_type))?;
let nested_class_rid = assembly.original_table_row_count(TableId::NestedClass) + 1;
let nested_class = NestedClassRaw {
rid: nested_class_rid,
token: Token::new(0x29000000 + nested_class_rid),
offset: 0,
nested_class: nested_rid,
enclosing_class: container_rid,
};
assembly.table_row_add(
TableId::NestedClass,
TableDataOwned::NestedClass(nested_class),
)?;
Ok(())
})
}