use crate::{
metadata::tables::{
CodedIndex, CodedIndexType, CustomAttributeBuilder, FieldBuilder, GenericParamBuilder,
InterfaceImplBuilder, MemberRefBuilder, MethodSpecBuilder, NestedClassBuilder, TableId,
TypeDefBuilder,
},
test::{
create_passing_test_assembly, create_test_assembly_with_error, get_testfile_wb,
TestAssembly,
},
Error, Result,
};
pub fn raw_token_validator_file_factory() -> Result<Vec<TestAssembly>> {
let mut assemblies = Vec::new();
let Some(clean_testfile) = get_testfile_wb() else {
return Err(Error::Other(
"WindowsBase.dll not available - test cannot run".to_string(),
));
};
assemblies.push(TestAssembly::new(&clean_testfile, true));
assemblies.push(create_assembly_with_invalid_typedef_extends()?);
assemblies.push(create_assembly_with_invalid_memberref()?);
assemblies.push(create_assembly_with_invalid_genericparam()?);
assemblies.push(create_assembly_with_invalid_interfaceimpl()?);
assemblies.push(create_assembly_with_invalid_methodspec()?);
assemblies.push(create_assembly_for_cross_table_validation()?);
Ok(assemblies)
}
pub fn create_assembly_with_invalid_typedef_extends() -> Result<TestAssembly> {
create_test_assembly_with_error(get_testfile_wb, "InvalidRid", |assembly| {
let invalid_extends =
CodedIndex::new(TableId::TypeRef, 999999, CodedIndexType::TypeDefOrRef);
TypeDefBuilder::new()
.name("InvalidType")
.namespace("Test")
.flags(0x00100000)
.extends(invalid_extends)
.build(assembly)?;
Ok(())
})
}
pub fn create_assembly_with_oversized_table() -> Result<TestAssembly> {
create_test_assembly_with_error(get_testfile_wb, "InvalidRid", |assembly| {
for i in 0..1000 {
TypeDefBuilder::new()
.name(format!("TestType{i}"))
.namespace("Overflow")
.flags(0x00100001)
.build(assembly)?;
}
Ok(())
})
}
pub fn create_assembly_with_invalid_coded_index() -> Result<TestAssembly> {
create_test_assembly_with_error(get_testfile_wb, "InvalidRid", |assembly| {
let invalid_extends =
CodedIndex::new(TableId::TypeRef, 999999, CodedIndexType::TypeDefOrRef);
TypeDefBuilder::new()
.name("InvalidCodedIndexType")
.namespace("Test")
.flags(0x00100000)
.extends(invalid_extends) .build(assembly)?;
Ok(())
})
}
pub fn create_assembly_with_missing_reference() -> Result<TestAssembly> {
create_test_assembly_with_error(get_testfile_wb, "InvalidRid", |assembly| {
let field_signature = vec![0x06, 0x08];
FieldBuilder::new()
.name("InvalidField")
.flags(0x0001)
.signature(&field_signature)
.build(assembly)?;
TypeDefBuilder::new()
.name("InvalidFieldList")
.namespace("Test")
.flags(0x00100000)
.build(assembly)?;
Ok(())
})
}
pub fn create_assembly_with_invalid_memberref() -> Result<TestAssembly> {
create_test_assembly_with_error(get_testfile_wb, "InvalidRid", |assembly| {
let invalid_class =
CodedIndex::new(TableId::TypeRef, 999999, CodedIndexType::MemberRefParent);
let signature = vec![0x00];
MemberRefBuilder::new()
.name("InvalidMember")
.class(invalid_class)
.signature(&signature)
.build(assembly)?;
Ok(())
})
}
pub fn create_assembly_with_rid_bounds_violation() -> Result<TestAssembly> {
create_test_assembly_with_error(get_testfile_wb, "InvalidRid", |assembly| {
for i in 0..100 {
TypeDefBuilder::new()
.name(format!("TestType{i}"))
.namespace("RidBoundsTest")
.flags(0x00100001)
.build(assembly)?;
}
Ok(())
})
}
pub fn create_assembly_with_invalid_customattribute() -> Result<TestAssembly> {
create_test_assembly_with_error(get_testfile_wb, "InvalidRid", |assembly| {
let typedef_token = TypeDefBuilder::new()
.name("TestType")
.namespace("Test")
.flags(0x00100000)
.build(assembly)?;
let invalid_constructor = CodedIndex::new(
TableId::MemberRef,
999999,
CodedIndexType::CustomAttributeType,
);
let parent = CodedIndex::new(
TableId::TypeDef,
typedef_token.placeholder(),
CodedIndexType::HasCustomAttribute,
);
CustomAttributeBuilder::new()
.parent(parent)
.constructor(invalid_constructor)
.value(&[])
.build(assembly)?;
Ok(())
})
}
pub fn create_assembly_with_invalid_genericparam() -> Result<TestAssembly> {
create_test_assembly_with_error(get_testfile_wb, "InvalidRid", |assembly| {
let invalid_owner =
CodedIndex::new(TableId::TypeDef, 999999, CodedIndexType::TypeOrMethodDef);
GenericParamBuilder::new()
.number(0)
.flags(0)
.owner(invalid_owner)
.name("T")
.build(assembly)?;
Ok(())
})
}
pub fn create_assembly_with_invalid_interfaceimpl() -> Result<TestAssembly> {
create_test_assembly_with_error(get_testfile_wb, "InvalidRid", |assembly| {
let typedef_token = TypeDefBuilder::new()
.name("TestInterface")
.namespace("Test")
.flags(0x000000A0)
.build(assembly)?;
let invalid_interface =
CodedIndex::new(TableId::TypeRef, 999999, CodedIndexType::TypeDefOrRef);
InterfaceImplBuilder::new()
.class(typedef_token.placeholder())
.interface(invalid_interface)
.build(assembly)?;
Ok(())
})
}
pub fn create_assembly_with_invalid_methodspec() -> Result<TestAssembly> {
create_test_assembly_with_error(get_testfile_wb, "InvalidRid", |assembly| {
let invalid_method =
CodedIndex::new(TableId::MethodDef, 999999, CodedIndexType::MethodDefOrRef);
let instantiation = vec![0x01, 0x1C];
MethodSpecBuilder::new()
.method(invalid_method)
.instantiation(&instantiation)
.build(assembly)?;
Ok(())
})
}
pub fn create_assembly_for_cross_table_validation() -> Result<TestAssembly> {
create_passing_test_assembly(get_testfile_wb, |assembly| {
let interface_type = TypeDefBuilder::new()
.name("ICrossTableInterface")
.namespace("CrossTableTest")
.flags(0x000000A1) .build(assembly)?;
let nested_type = TypeDefBuilder::new()
.name("NestedType")
.namespace("CrossTableTest")
.flags(0x00100002) .build(assembly)?;
NestedClassBuilder::new()
.nested_class(nested_type.placeholder())
.enclosing_class(interface_type.placeholder())
.build(assembly)?;
Ok(())
})
}