use crate::{
metadata::{
tables::{
ClassLayoutRaw, FieldBuilder, FieldLayoutRaw, TableDataOwned, TableId, TypeDefBuilder,
},
token::Token,
},
test::{create_test_assembly_with_error, get_testfile_wb, TestAssembly},
Error, Result,
};
pub fn raw_layout_constraint_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_null_field_reference()?);
assemblies.push(create_assembly_with_invalid_field_offset()?);
assemblies.push(create_assembly_with_invalid_packing_size()?);
assemblies.push(create_assembly_with_excessive_class_size()?);
Ok(assemblies)
}
pub fn create_assembly_with_overlapping_fields() -> Result<TestAssembly> {
create_test_assembly_with_error(get_testfile_wb, "Malformed", |assembly| {
let _typedef_token = TypeDefBuilder::new()
.name("OverlappingFieldsType")
.namespace("Test")
.flags(0x00100108) .build(assembly)?;
let field_token = FieldBuilder::new()
.name("TestField")
.flags(0x0001)
.signature(&[0x06, 0x08])
.build(assembly)?;
for i in 1..=1001 {
let field_layout = FieldLayoutRaw {
field_offset: 4, field: field_token.placeholder(),
rid: i,
token: Token::new(0x10000000 + i),
offset: ((i - 1) * 8) as usize, };
assembly.table_row_update(
TableId::FieldLayout,
i,
TableDataOwned::FieldLayout(field_layout),
)?;
}
Ok(())
})
}
pub fn create_assembly_with_invalid_packing_size() -> Result<TestAssembly> {
create_test_assembly_with_error(get_testfile_wb, "Malformed", |assembly| {
let typedef_token = TypeDefBuilder::new()
.name("InvalidPackingType")
.namespace("Test")
.flags(0x00100000)
.build(assembly)?;
let class_layout = ClassLayoutRaw {
packing_size: 3, class_size: 16,
parent: typedef_token.placeholder(),
rid: 1,
token: Token::new(0x0F000001), offset: 0,
};
assembly.table_row_update(
TableId::ClassLayout,
1,
TableDataOwned::ClassLayout(class_layout),
)?;
Ok(())
})
}
pub fn create_assembly_with_excessive_class_size() -> Result<TestAssembly> {
create_test_assembly_with_error(get_testfile_wb, "Malformed", |assembly| {
let typedef_token = TypeDefBuilder::new()
.name("ExcessiveSizeType")
.namespace("Test")
.flags(0x00100000)
.build(assembly)?;
let class_layout = ClassLayoutRaw {
packing_size: 1,
class_size: 0x80000000, parent: typedef_token.placeholder(),
rid: 1,
token: Token::new(0x0F000001), offset: 0,
};
assembly.table_row_update(
TableId::ClassLayout,
1,
TableDataOwned::ClassLayout(class_layout),
)?;
Ok(())
})
}
pub fn create_assembly_with_invalid_field_offset() -> Result<TestAssembly> {
create_test_assembly_with_error(get_testfile_wb, "Malformed", |assembly| {
let _typedef_token = TypeDefBuilder::new()
.name("InvalidOffsetType")
.namespace("Test")
.flags(0x00100108) .build(assembly)?;
let field_token = FieldBuilder::new()
.name("InvalidField")
.flags(0x0001)
.signature(&[0x06, 0x08])
.build(assembly)?;
let field_layout = FieldLayoutRaw {
field_offset: 0x80000000, field: field_token.placeholder(),
rid: 1,
token: Token::new(0x10000001), offset: 0, };
assembly.table_row_update(
TableId::FieldLayout,
1,
TableDataOwned::FieldLayout(field_layout),
)?;
Ok(())
})
}
pub fn create_assembly_with_null_field_reference() -> Result<TestAssembly> {
create_test_assembly_with_error(get_testfile_wb, "Malformed", |assembly| {
let _typedef_token = TypeDefBuilder::new()
.name("NullFieldRefType")
.namespace("Test")
.flags(0x00100108) .build(assembly)?;
let field_layout = FieldLayoutRaw {
field_offset: 0,
field: 0, rid: 1,
token: Token::new(0x10000001), offset: 0,
};
assembly.table_row_update(
TableId::FieldLayout,
1,
TableDataOwned::FieldLayout(field_layout),
)?;
Ok(())
})
}
pub fn create_assembly_with_boundary_field_offset() -> Result<TestAssembly> {
create_test_assembly_with_error(get_testfile_wb, "Malformed", |assembly| {
let _typedef_token = TypeDefBuilder::new()
.name("BoundaryOffsetType")
.namespace("Test")
.flags(0x00100108) .build(assembly)?;
let field_token = FieldBuilder::new()
.name("BoundaryField")
.flags(0x0001)
.signature(&[0x06, 0x08])
.build(assembly)?;
let field_layout = FieldLayoutRaw {
field_offset: 0x7FFFFFFF, field: field_token.placeholder(),
rid: 1,
token: Token::new(0x10000001), offset: 0, };
assembly.table_row_update(
TableId::FieldLayout,
1,
TableDataOwned::FieldLayout(field_layout),
)?;
Ok(())
})
}