Skip to content

Commit

Permalink
[verifier] Cannot call init (MystenLabs#2151)
Browse files Browse the repository at this point in the history
* [verifier] Cannot call init

- Added rule to stop re-calling init
- Added init tests
  • Loading branch information
tnowacki authored May 24, 2022
1 parent 5c16252 commit 53ace39
Show file tree
Hide file tree
Showing 13 changed files with 183 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
processed 2 tasks

task 1 'publish'. lines 5-25:
Error: Failed to verify the Move module, reason: "_::M1. 'init' function cannot be public".
Error: Failed to verify the Move module, reason: "_::M1. 'init' function must be private".
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
processed 1 task

task 0 'publish'. lines 4-17:
Error: Failed to verify the Move module, reason: "_::M::init at offset 1. Cannot call a module's 'init' function from another Move function".
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

//# publish
module 0x0.M {
import 0x2.TxContext;
init(ctx: &mut TxContext.TxContext) {
label l0:
abort 0;
}

public(script) init_again(ctx: &mut TxContext.TxContext) {
label l0:
Self.init(move(ctx));
return;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
processed 1 task

task 0 'publish'. lines 4-11:
Error: Failed to verify the Move module, reason: "_::M. 'init' function cannot have type parameters".
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

//# publish
module 0x0.M {
import 0x2.TxContext;
init<T>(ctx: &mut TxContext.TxContext) {
label l0:
abort 0;
}
}
10 changes: 10 additions & 0 deletions crates/sui-verifier-transactional-tests/tests/init/not_private.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
processed 3 tasks

task 0 'publish'. lines 4-11:
Error: Failed to verify the Move module, reason: "_::M. 'init' function must be private".

task 1 'publish'. lines 13-20:
Error: Failed to verify the Move module, reason: "_::M. 'init' function must be private".

task 2 'publish'. lines 22-29:
Error: Failed to verify the Move module, reason: "_::M. 'init' function must be private".
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

//# publish
module 0x0.M {
import 0x2.TxContext;
public init(ctx: &mut TxContext.TxContext) {
label l0:
abort 0;
}
}

//# publish
module 0x0.M {
import 0x2.TxContext;
public(script) init(ctx: &mut TxContext.TxContext) {
label l0:
abort 0;
}
}

//# publish
module 0x0.M {
import 0x2.TxContext;
public(friend) init(ctx: &mut TxContext.TxContext) {
label l0:
abort 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
processed 4 tasks

task 0 'publish'. lines 4-11:
Error: Failed to verify the Move module, reason: "Expected parameter for _::M::init to be &mut mut Sui::TxContext::TxContext, but found u64".

task 1 'publish'. lines 13-20:
Error: Failed to verify the Move module, reason: "Expected parameter for _::TxContext::init to be &mut mut Sui::TxContext::TxContext, but found _::TxContext::TxContext".

task 2 'publish'. lines 22-29:
Error: Failed to verify the Move module, reason: "Expected parameter for _::M::init to be &mut mut Sui::TxContext::TxContext, but found &Sui::TxContext::TxContext".

task 3 'publish'. lines 32-39:
Error: Failed to verify the Move module, reason: "Expected parameter for _::M::init to be &mut mut Sui::TxContext::TxContext, but found Sui::TxContext::TxContext".
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

//# publish
module 0x0.M {
import 0x2.TxContext;
init(ctx: u64) {
label l0:
abort 0;
}
}

//# publish
module 0x0.TxContext {
struct TxContext { value: u64 }
init(ctx: Self.TxContext) {
label l0:
abort 0;
}
}

//# publish
module 0x0.M {
import 0x2.TxContext;
init(ctx: &TxContext.TxContext) {
label l0:
abort 0;
}
}


//# publish
module 0x0.M {
import 0x2.TxContext;
init(ctx: TxContext.TxContext) {
label l0:
abort 0;
}
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
processed 1 task

task 0 'publish'. lines 4-11:
Error: Failed to verify the Move module, reason: "_::M, 'init' function cannot have return values".
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

//# publish
module 0x0.M {
import 0x2.TxContext;
init(ctx: &mut TxContext.TxContext): u64 {
label l0:
abort 0;
}
}
42 changes: 40 additions & 2 deletions crates/sui-verifier/src/entry_points_verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use move_binary_format::{
access::ModuleAccess,
binary_views::BinaryIndexedView,
file_format::{AbilitySet, FunctionDefinition, SignatureToken, Visibility},
file_format::{AbilitySet, Bytecode, FunctionDefinition, SignatureToken, Visibility},
CompiledModule,
};
use move_core_types::{account_address::AccountAddress, ident_str, identifier::IdentStr};
Expand Down Expand Up @@ -38,6 +38,9 @@ pub const INIT_FN_NAME: &IdentStr = ident_str!("init");
/// - The function cannot have any return values
pub fn verify_module(module: &CompiledModule) -> SuiResult {
for func_def in &module.function_defs {
verify_init_not_called(module, func_def)
.map_err(|error| SuiError::ModuleVerificationFailure { error })?;

let handle = module.function_handle_at(func_def.function);
let name = module.identifier_at(handle.name);
if name == INIT_FN_NAME {
Expand All @@ -59,13 +62,48 @@ pub fn verify_module(module: &CompiledModule) -> SuiResult {
Ok(())
}

fn verify_init_not_called(
module: &CompiledModule,
fdef: &FunctionDefinition,
) -> Result<(), String> {
let code = match &fdef.code {
None => return Ok(()),
Some(code) => code,
};
code.code
.iter()
.enumerate()
.filter_map(|(idx, instr)| match instr {
Bytecode::Call(fhandle_idx) => Some((idx, module.function_handle_at(*fhandle_idx))),
Bytecode::CallGeneric(finst_idx) => {
let finst = module.function_instantiation_at(*finst_idx);
Some((idx, module.function_handle_at(finst.handle)))
}
_ => None,
})
.try_for_each(|(idx, fhandle)| {
let name = module.identifier_at(fhandle.name);
if name == INIT_FN_NAME {
Err(format!(
"{}::{} at offset {}. Cannot call a module's '{}' function from another Move function",
module.self_id(),
name,
idx,
INIT_FN_NAME
))
} else {
Ok(())
}
})
}

/// Checks if this module has a conformant `init`
fn verify_init_function(module: &CompiledModule, fdef: &FunctionDefinition) -> Result<(), String> {
let view = &BinaryIndexedView::Module(module);

if fdef.visibility != Visibility::Private {
return Err(format!(
"{}. '{}' function cannot be public",
"{}. '{}' function must be private",
module.self_id(),
INIT_FN_NAME
));
Expand Down

0 comments on commit 53ace39

Please sign in to comment.