1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use move_binary_format::{
access::ModuleAccess,
binary_views::BinaryIndexedView,
errors::{Location, PartialVMError, PartialVMResult, VMResult},
file_format::{
CompiledModule, CompiledScript, SignatureIndex, SignatureToken, TableIndex, Visibility,
},
file_format_common::VERSION_1,
IndexKind,
};
use move_core_types::{identifier::IdentStr, vm_status::StatusCode};
pub fn verify_script(script: &CompiledScript) -> VMResult<()> {
let resolver = &BinaryIndexedView::Script(script);
let parameters = script.parameters;
let return_type_opt = None;
verify_main_signature_impl(resolver, parameters, return_type_opt)
.map_err(|e| e.finish(Location::Script))
}
pub fn verify_module_script_function(module: &CompiledModule, name: &IdentStr) -> VMResult<()> {
let fdef_opt = module.function_defs().iter().enumerate().find(|(_, fdef)| {
module.identifier_at(module.function_handle_at(fdef.function).name) == name
});
let (idx, fdef) = fdef_opt.ok_or_else(|| {
PartialVMError::new(StatusCode::VERIFICATION_ERROR)
.with_message("function not found in verify_module_script_function".to_string())
.finish(Location::Module(module.self_id()))
})?;
match fdef.visibility {
Visibility::Script => (),
Visibility::Private | Visibility::Friend | Visibility::Public => {
return Err(PartialVMError::new(
StatusCode::EXECUTE_SCRIPT_FUNCTION_CALLED_ON_NON_SCRIPT_VISIBLE,
)
.at_index(IndexKind::FunctionDefinition, idx as TableIndex)
.finish(Location::Module(module.self_id())))
}
}
let resolver = &BinaryIndexedView::Module(module);
let fhandle = module.function_handle_at(fdef.function);
let parameters = fhandle.parameters;
let return_type_opt = Some(fhandle.return_);
verify_main_signature_impl(resolver, parameters, return_type_opt).map_err(|e| {
e.at_index(IndexKind::FunctionDefinition, idx as TableIndex)
.finish(Location::Module(module.self_id()))
})
}
fn verify_main_signature_impl(
resolver: &BinaryIndexedView,
parameters: SignatureIndex,
return_type_opt: Option<SignatureIndex>,
) -> PartialVMResult<()> {
use SignatureToken as S;
let arguments = &resolver.signature_at(parameters).0;
let all_args_have_valid_type = if resolver.version() <= VERSION_1 {
arguments
.iter()
.skip_while(|typ| matches!(typ, S::Reference(inner) if matches!(&**inner, S::Signer)))
.all(|typ| typ.is_valid_for_constant())
} else {
arguments
.iter()
.skip_while(|typ| matches!(typ, S::Signer))
.all(|typ| typ.is_valid_for_constant())
};
let has_valid_return_type = match return_type_opt {
Some(idx) => resolver.signature_at(idx).0.is_empty(),
None => true,
};
if !all_args_have_valid_type || !has_valid_return_type {
Err(PartialVMError::new(
StatusCode::INVALID_MAIN_FUNCTION_SIGNATURE,
))
} else {
Ok(())
}
}