use crate::{
metadata::{
tables::{CodedIndex, CodedIndexType, MethodDefRaw, TableDataOwned, TableId, TypeDefRaw},
token::Token,
},
test::{create_test_assembly, get_testfile_mscorlib, TestAssembly},
Error, Result,
};
pub fn owned_method_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_empty_method_name()?);
assemblies.push(create_assembly_with_abstract_non_virtual_method()?);
assemblies.push(create_assembly_with_static_virtual_method()?);
assemblies.push(create_assembly_with_invalid_instance_constructor()?);
assemblies.push(create_assembly_with_abstract_method_with_rva()?);
Ok(assemblies)
}
pub fn create_assembly_with_empty_method_name() -> Result<TestAssembly> {
create_test_assembly(get_testfile_mscorlib, |assembly| {
let type_name_index = assembly
.string_add("TypeWithEmptyMethodName")
.map_err(|e| Error::Other(format!("Failed to add type name: {e}")))?;
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: 0x00000001, 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("")
.map_err(|e| Error::Other(format!("Failed to add empty method name: {e}")))?;
let signature_bytes = vec![0x00, 0x00]; let signature_index = assembly
.blob_add(&signature_bytes)
.map_err(|e| Error::Other(format!("Failed to add signature: {e}")))?;
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))
.map_err(|e| Error::Other(format!("Failed to add type: {e}")))?;
assembly
.table_row_add(
TableId::MethodDef,
TableDataOwned::MethodDef(invalid_method),
)
.map_err(|e| Error::Other(format!("Failed to add invalid method: {e}")))?;
Ok(())
})
}
pub fn create_assembly_with_abstract_non_virtual_method() -> Result<TestAssembly> {
create_test_assembly(get_testfile_mscorlib, |assembly| {
let type_name_index = assembly
.string_add("AbstractTypeWithNonVirtualMethod")
.map_err(|e| Error::Other(format!("Failed to add type name: {e}")))?;
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: 0x00000081, 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 method_name_index = assembly
.string_add("AbstractNonVirtualMethod")
.map_err(|e| Error::Other(format!("Failed to add method name: {e}")))?;
let signature_bytes = vec![0x00, 0x00]; let signature_index = assembly
.blob_add(&signature_bytes)
.map_err(|e| Error::Other(format!("Failed to add signature: {e}")))?;
let invalid_method = MethodDefRaw {
rid: method_rid,
token: Token::new(0x06000000 + method_rid),
offset: 0,
rva: 0,
impl_flags: 0,
flags: 0x0406, name: method_name_index.placeholder(),
signature: signature_index.placeholder(),
param_list: 1,
};
assembly
.table_row_add(TableId::TypeDef, TableDataOwned::TypeDef(type_def))
.map_err(|e| Error::Other(format!("Failed to add type: {e}")))?;
assembly
.table_row_add(
TableId::MethodDef,
TableDataOwned::MethodDef(invalid_method),
)
.map_err(|e| Error::Other(format!("Failed to add invalid method: {e}")))?;
Ok(())
})
}
pub fn create_assembly_with_static_virtual_method() -> Result<TestAssembly> {
create_test_assembly(get_testfile_mscorlib, |assembly| {
let type_name_index = assembly
.string_add("TypeWithStaticVirtualMethod")
.map_err(|e| Error::Other(format!("Failed to add type name: {e}")))?;
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: 0x00000001, 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 method_name_index = assembly
.string_add("StaticVirtualMethod")
.map_err(|e| Error::Other(format!("Failed to add method name: {e}")))?;
let signature_bytes = vec![0x00, 0x00]; let signature_index = assembly
.blob_add(&signature_bytes)
.map_err(|e| Error::Other(format!("Failed to add signature: {e}")))?;
let invalid_method = MethodDefRaw {
rid: method_rid,
token: Token::new(0x06000000 + method_rid),
offset: 0,
rva: 0,
impl_flags: 0,
flags: 0x0056, name: method_name_index.placeholder(),
signature: signature_index.placeholder(),
param_list: 1,
};
assembly
.table_row_add(TableId::TypeDef, TableDataOwned::TypeDef(type_def))
.map_err(|e| Error::Other(format!("Failed to add type: {e}")))?;
assembly
.table_row_add(
TableId::MethodDef,
TableDataOwned::MethodDef(invalid_method),
)
.map_err(|e| Error::Other(format!("Failed to add invalid method: {e}")))?;
Ok(())
})
}
pub fn create_assembly_with_invalid_instance_constructor() -> Result<TestAssembly> {
create_test_assembly(get_testfile_mscorlib, |assembly| {
let type_name_index = assembly
.string_add("TypeWithInvalidConstructor")
.map_err(|e| Error::Other(format!("Failed to add type name: {e}")))?;
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: 0x00000001, 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 ctor_name_index = assembly
.string_add(".ctor")
.map_err(|e| Error::Other(format!("Failed to add constructor name: {e}")))?;
let signature_bytes = vec![0x00, 0x00]; let signature_index = assembly
.blob_add(&signature_bytes)
.map_err(|e| Error::Other(format!("Failed to add signature: {e}")))?;
let invalid_method = MethodDefRaw {
rid: method_rid,
token: Token::new(0x06000000 + method_rid),
offset: 0,
rva: 0x1000, impl_flags: 0,
flags: 0x1806, name: ctor_name_index.placeholder(),
signature: signature_index.placeholder(),
param_list: 1,
};
assembly
.table_row_add(TableId::TypeDef, TableDataOwned::TypeDef(type_def))
.map_err(|e| Error::Other(format!("Failed to add type: {e}")))?;
assembly
.table_row_add(
TableId::MethodDef,
TableDataOwned::MethodDef(invalid_method),
)
.map_err(|e| Error::Other(format!("Failed to add invalid method: {e}")))?;
Ok(())
})
}
pub fn create_assembly_with_abstract_method_with_rva() -> Result<TestAssembly> {
create_test_assembly(get_testfile_mscorlib, |assembly| {
let type_name_index = assembly
.string_add("AbstractTypeWithRVAMethod")
.map_err(|e| Error::Other(format!("Failed to add type name: {e}")))?;
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: 0x00000081, 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 method_name_index = assembly
.string_add("AbstractMethodWithRVA")
.map_err(|e| Error::Other(format!("Failed to add method name: {e}")))?;
let signature_bytes = vec![0x00, 0x00]; let signature_index = assembly
.blob_add(&signature_bytes)
.map_err(|e| Error::Other(format!("Failed to add signature: {e}")))?;
let invalid_method = MethodDefRaw {
rid: method_rid,
token: Token::new(0x06000000 + method_rid),
offset: 0,
rva: 0x1000, impl_flags: 0,
flags: 0x0446, name: method_name_index.placeholder(),
signature: signature_index.placeholder(),
param_list: 1,
};
assembly
.table_row_add(TableId::TypeDef, TableDataOwned::TypeDef(type_def))
.map_err(|e| Error::Other(format!("Failed to add type: {e}")))?;
assembly
.table_row_add(
TableId::MethodDef,
TableDataOwned::MethodDef(invalid_method),
)
.map_err(|e| Error::Other(format!("Failed to add invalid method: {e}")))?;
Ok(())
})
}