use crate::{
metadata::{
customattributes::{
encode_custom_attribute_value, CustomAttributeArgument, CustomAttributeNamedArgument,
CustomAttributeValue,
},
tables::{CodedIndex, CodedIndexType, CustomAttributeRaw, TableDataOwned, TableId},
token::Token,
},
test::{create_test_assembly, get_testfile_mscorlib, TestAssembly},
Error, Result,
};
pub fn owned_attribute_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_excessive_fixed_args()?);
assemblies.push(create_assembly_with_excessive_named_args()?);
assemblies.push(create_assembly_with_duplicate_named_args()?);
assemblies.push(create_assembly_with_empty_named_arg_name()?);
assemblies.push(create_assembly_with_null_character_string()?);
assemblies.push(create_assembly_with_excessive_string_length()?);
Ok(assemblies)
}
pub fn create_assembly_with_excessive_fixed_args() -> Result<TestAssembly> {
create_test_assembly(get_testfile_mscorlib, |assembly| {
let mut fixed_args = Vec::new();
for i in 0..25 {
fixed_args.push(CustomAttributeArgument::I4(i));
}
let custom_attr_value = CustomAttributeValue {
fixed_args,
named_args: vec![],
};
let blob_data = encode_custom_attribute_value(&custom_attr_value)
.map_err(|e| Error::Other(format!("Failed to encode custom attribute: {e}")))?;
let blob_index = assembly
.blob_add(&blob_data)
.map_err(|e| Error::Other(format!("Failed to add blob: {e}")))?;
let next_rid = assembly.original_table_row_count(TableId::CustomAttribute) + 1;
let invalid_custom_attr = CustomAttributeRaw {
rid: next_rid,
token: Token::new(0x0C000000 + next_rid),
offset: 0,
parent: CodedIndex::new(TableId::TypeDef, 1, CodedIndexType::HasCustomAttribute),
constructor: CodedIndex::new(
TableId::MethodDef,
1,
CodedIndexType::CustomAttributeType,
),
value: blob_index.placeholder(),
};
assembly
.table_row_add(
TableId::CustomAttribute,
TableDataOwned::CustomAttribute(invalid_custom_attr),
)
.map_err(|e| Error::Other(format!("Failed to add custom attribute: {e}")))?;
Ok(())
})
}
pub fn create_assembly_with_excessive_named_args() -> Result<TestAssembly> {
create_test_assembly(get_testfile_mscorlib, |assembly| {
let mut named_args = Vec::new();
for i in 0..55 {
named_args.push(CustomAttributeNamedArgument {
is_field: false,
name: format!("Property{i}"),
arg_type: "String".to_string(),
value: CustomAttributeArgument::String(format!("Value{i}")),
});
}
let custom_attr_value = CustomAttributeValue {
fixed_args: vec![],
named_args,
};
let blob_data = encode_custom_attribute_value(&custom_attr_value)
.map_err(|e| Error::Other(format!("Failed to encode custom attribute: {e}")))?;
let blob_index = assembly
.blob_add(&blob_data)
.map_err(|e| Error::Other(format!("Failed to add blob: {e}")))?;
let next_rid = assembly.original_table_row_count(TableId::CustomAttribute) + 1;
let invalid_custom_attr = CustomAttributeRaw {
rid: next_rid,
token: Token::new(0x0C000000 + next_rid),
offset: 0,
parent: CodedIndex::new(TableId::TypeDef, 1, CodedIndexType::HasCustomAttribute),
constructor: CodedIndex::new(
TableId::MethodDef,
1,
CodedIndexType::CustomAttributeType,
),
value: blob_index.placeholder(),
};
assembly
.table_row_add(
TableId::CustomAttribute,
TableDataOwned::CustomAttribute(invalid_custom_attr),
)
.map_err(|e| Error::Other(format!("Failed to add custom attribute: {e}")))?;
Ok(())
})
}
pub fn create_assembly_with_duplicate_named_args() -> Result<TestAssembly> {
create_test_assembly(get_testfile_mscorlib, |assembly| {
let named_args = vec![
CustomAttributeNamedArgument {
is_field: false,
name: "DuplicateName".to_string(),
arg_type: "String".to_string(),
value: CustomAttributeArgument::String("Value1".to_string()),
},
CustomAttributeNamedArgument {
is_field: false,
name: "DuplicateName".to_string(), arg_type: "String".to_string(),
value: CustomAttributeArgument::String("Value2".to_string()),
},
];
let custom_attr_value = CustomAttributeValue {
fixed_args: vec![],
named_args,
};
let blob_data = encode_custom_attribute_value(&custom_attr_value)
.map_err(|e| Error::Other(format!("Failed to encode custom attribute: {e}")))?;
let blob_index = assembly
.blob_add(&blob_data)
.map_err(|e| Error::Other(format!("Failed to add blob: {e}")))?;
let next_rid = assembly.original_table_row_count(TableId::CustomAttribute) + 1;
let invalid_custom_attr = CustomAttributeRaw {
rid: next_rid,
token: Token::new(0x0C000000 + next_rid),
offset: 0,
parent: CodedIndex::new(TableId::TypeDef, 1, CodedIndexType::HasCustomAttribute),
constructor: CodedIndex::new(
TableId::MethodDef,
1,
CodedIndexType::CustomAttributeType,
),
value: blob_index.placeholder(),
};
assembly
.table_row_add(
TableId::CustomAttribute,
TableDataOwned::CustomAttribute(invalid_custom_attr),
)
.map_err(|e| Error::Other(format!("Failed to add custom attribute: {e}")))?;
Ok(())
})
}
pub fn create_assembly_with_empty_named_arg_name() -> Result<TestAssembly> {
create_test_assembly(get_testfile_mscorlib, |assembly| {
let named_args = vec![CustomAttributeNamedArgument {
is_field: false,
name: "".to_string(), arg_type: "String".to_string(),
value: CustomAttributeArgument::String("Value".to_string()),
}];
let custom_attr_value = CustomAttributeValue {
fixed_args: vec![],
named_args,
};
let blob_data = encode_custom_attribute_value(&custom_attr_value)
.map_err(|e| Error::Other(format!("Failed to encode custom attribute: {e}")))?;
let blob_index = assembly
.blob_add(&blob_data)
.map_err(|e| Error::Other(format!("Failed to add blob: {e}")))?;
let next_rid = assembly.original_table_row_count(TableId::CustomAttribute) + 1;
let invalid_custom_attr = CustomAttributeRaw {
rid: next_rid,
token: Token::new(0x0C000000 + next_rid),
offset: 0,
parent: CodedIndex::new(TableId::TypeDef, 1, CodedIndexType::HasCustomAttribute),
constructor: CodedIndex::new(
TableId::MethodDef,
1,
CodedIndexType::CustomAttributeType,
),
value: blob_index.placeholder(),
};
assembly
.table_row_add(
TableId::CustomAttribute,
TableDataOwned::CustomAttribute(invalid_custom_attr),
)
.map_err(|e| Error::Other(format!("Failed to add custom attribute: {e}")))?;
Ok(())
})
}
pub fn create_assembly_with_null_character_string() -> Result<TestAssembly> {
create_test_assembly(get_testfile_mscorlib, |assembly| {
let fixed_args = vec![CustomAttributeArgument::String(
"String\0WithNull".to_string(),
)];
let custom_attr_value = CustomAttributeValue {
fixed_args,
named_args: vec![],
};
let blob_data = encode_custom_attribute_value(&custom_attr_value)
.map_err(|e| Error::Other(format!("Failed to encode custom attribute: {e}")))?;
let blob_index = assembly
.blob_add(&blob_data)
.map_err(|e| Error::Other(format!("Failed to add blob: {e}")))?;
let next_rid = assembly.original_table_row_count(TableId::CustomAttribute) + 1;
let invalid_custom_attr = CustomAttributeRaw {
rid: next_rid,
token: Token::new(0x0C000000 + next_rid),
offset: 0,
parent: CodedIndex::new(TableId::TypeDef, 1, CodedIndexType::HasCustomAttribute),
constructor: CodedIndex::new(
TableId::MethodDef,
1,
CodedIndexType::CustomAttributeType,
),
value: blob_index.placeholder(),
};
assembly
.table_row_add(
TableId::CustomAttribute,
TableDataOwned::CustomAttribute(invalid_custom_attr),
)
.map_err(|e| Error::Other(format!("Failed to add custom attribute: {e}")))?;
Ok(())
})
}
pub fn create_assembly_with_excessive_string_length() -> Result<TestAssembly> {
create_test_assembly(get_testfile_mscorlib, |assembly| {
let long_string = "A".repeat(15_000);
let fixed_args = vec![CustomAttributeArgument::String(long_string)];
let custom_attr_value = CustomAttributeValue {
fixed_args,
named_args: vec![],
};
let blob_data = encode_custom_attribute_value(&custom_attr_value)
.map_err(|e| Error::Other(format!("Failed to encode custom attribute: {e}")))?;
let blob_index = assembly
.blob_add(&blob_data)
.map_err(|e| Error::Other(format!("Failed to add blob: {e}")))?;
let next_rid = assembly.original_table_row_count(TableId::CustomAttribute) + 1;
let invalid_custom_attr = CustomAttributeRaw {
rid: next_rid,
token: Token::new(0x0C000000 + next_rid),
offset: 0,
parent: CodedIndex::new(TableId::TypeDef, 1, CodedIndexType::HasCustomAttribute),
constructor: CodedIndex::new(
TableId::MethodDef,
1,
CodedIndexType::CustomAttributeType,
),
value: blob_index.placeholder(),
};
assembly
.table_row_add(
TableId::CustomAttribute,
TableDataOwned::CustomAttribute(invalid_custom_attr),
)
.map_err(|e| Error::Other(format!("Failed to add custom attribute: {e}")))?;
Ok(())
})
}