Skip to content

Commit

Permalink
[transactional tests][bytecode verifier] Start bytecode verifier test…
Browse files Browse the repository at this point in the history
… migration

- Added two tests to start (small example for this PR)
- Improved VM error printing

Closes: aptos-labs#8904
  • Loading branch information
Todd Nowacki authored and bors-libra committed Aug 11, 2021
1 parent 0f90c56 commit e2b392f
Showing 12 changed files with 155 additions and 14 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -61,6 +61,7 @@ members = [
"language/bytecode-verifier",
"language/bytecode-verifier/bytecode-verifier-tests",
"language/bytecode-verifier/invalid-mutations",
"language/bytecode-verifier/transactional-tests",
"language/compiler",
"language/compiler/bytecode-source-map",
"language/compiler/ir-to-bytecode",
19 changes: 19 additions & 0 deletions language/bytecode-verifier/transactional-tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "bytecode-verifier-transactional-tests"
version = "0.1.0"
authors = ["Diem Association <[email protected]>"]
publish = false
edition = "2018"
license = "Apache-2.0"

[dependencies]
diem-workspace-hack = { path = "../../../common/workspace-hack" }

[dev-dependencies]
datatest-stable = "0.1.1"
move-command-line-common = { path = "../../move-command-line-common" }
move-transactional-test-runner = { path = "../../testing-infra/transactional-test-runner" }

[[test]]
name = "tests"
harness = false
6 changes: 6 additions & 0 deletions language/bytecode-verifier/transactional-tests/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

// Empty src/lib.rs to get rusty-tags working.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
processed 4 tasks

task 0 'publish'. lines 1-13:
Error: Unable to publish module '00000000000000000000000000000001::Tester'. Got VMError: {
major_status: READREF_EXISTS_MUTABLE_BORROW_ERROR,
sub_status: None,
location: 0x1::Tester,
indices: [(FunctionDefinition, 0)],
offsets: [(FunctionDefinitionIndex(0), 6)],
}

task 1 'publish'. lines 15-27:
Error: Unable to publish module '00000000000000000000000000000001::Tester2'. Got VMError: {
major_status: READREF_EXISTS_MUTABLE_BORROW_ERROR,
sub_status: None,
location: 0x1::Tester2,
indices: [(FunctionDefinition, 0)],
offsets: [(FunctionDefinitionIndex(0), 6)],
}

task 2 'publish'. lines 29-41:
Error: Unable to publish module '00000000000000000000000000000001::Tester3'. Got VMError: {
major_status: READREF_EXISTS_MUTABLE_BORROW_ERROR,
sub_status: None,
location: 0x1::Tester3,
indices: [(FunctionDefinition, 0)],
offsets: [(FunctionDefinitionIndex(0), 6)],
}

task 3 'publish'. lines 43-55:
Error: Unable to publish module '00000000000000000000000000000001::Tester4'. Got VMError: {
major_status: READREF_EXISTS_MUTABLE_BORROW_ERROR,
sub_status: None,
location: 0x1::Tester4,
indices: [(FunctionDefinition, 0)],
offsets: [(FunctionDefinitionIndex(0), 6)],
}
Original file line number Diff line number Diff line change
@@ -1,54 +1,55 @@
//# publish --address 0x1
module Tester {
eqtest1() {
let x: u64;
let r: &mut u64;

x = 0;
r = &mut x;
// invalid read of mutable ref, does not currently own its data
_ = copy(r) == copy(r);
return;
}
}
// check: READREF_EXISTS_MUTABLE_BORROW_ERROR

//! new-transaction
//# publish --address 0x1
module Tester2 {
eqtest2() {
let x: u64;
let r: &mut u64;

x = 0;
r = &mut x;
// invalid read of mutable ref, does not currently own its data
_ = copy(r) == move(r);
return;
}
}
// check: READREF_EXISTS_MUTABLE_BORROW_ERROR

//! new-transaction
//# publish --address 0x1
module Tester3 {
neqtest1() {
let x: u64;
let r: &mut u64;

x = 0;
r = &mut x;
// invalid read of mutable ref, does not currently own its data
_ = copy(r) != copy(r);
return;
}
}
// check: READREF_EXISTS_MUTABLE_BORROW_ERROR

//! new-transaction
//# publish --address 0x1
module Tester4 {
neqtest2() {
let x: u64;
let r: &mut u64;

x = 0;
r = &mut x;
// invalid read of mutable ref, does not currently own its data
_ = copy(r) != move(r);
return;
}
}
// check: READREF_EXISTS_MUTABLE_BORROW_ERROR
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
processed 1 task
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//# publish --address 0x1

// testing valid usages of == and != over references
module Tester {
eqtest1() {
let x: u64;
7 changes: 7 additions & 0 deletions language/bytecode-verifier/transactional-tests/tests/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

pub const TEST_DIR: &str = "tests";
use move_transactional_test_runner::vm_test_harness::run_test;

datatest_stable::harness!(run_test, TEST_DIR, r".*\.(mvir|move)$");
Original file line number Diff line number Diff line change
@@ -9,15 +9,21 @@ use crate::{
tasks::{InitCommand, KnownCommandFormat, SyntaxChoice, TaskInput},
};
use anyhow::*;
use move_binary_format::{errors::VMResult, file_format::CompiledScript, CompiledModule};
use move_binary_format::{
access::ModuleAccess,
errors::{Location, VMError, VMResult},
file_format::CompiledScript,
CompiledModule,
};
use move_core_types::{
account_address::AccountAddress,
identifier::IdentStr,
language_storage::{ModuleId, StructTag, TypeTag},
transaction_argument::{convert_txn_args, TransactionArgument},
};
use move_lang::{
compiled_unit::CompiledUnit, shared::verify_and_create_named_address_mapping,
compiled_unit::CompiledUnit,
shared::{verify_and_create_named_address_mapping, AddressBytes},
FullyCompiledProgram,
};
use move_stdlib::move_stdlib_named_addresses;
@@ -95,6 +101,16 @@ impl<'a> MoveTestAdapter<'a> for SimpleVMTestAdapter<'a> {
Ok(())
})
.unwrap();
let mut addr_to_name_mapping = BTreeMap::new();
for (name, addr) in move_stdlib_named_addresses() {
let prev = addr_to_name_mapping.insert(addr, name);
assert!(prev.is_none());
}
for module in &*MOVE_STDLIB_COMPILED {
let bytes = AddressBytes::new(module.address().to_u8());
let named_addr = addr_to_name_mapping.get(&bytes).unwrap().clone();
adapter.compiled_state.add(Some(named_addr), module.clone());
}
adapter
}

@@ -114,9 +130,9 @@ impl<'a> MoveTestAdapter<'a> for SimpleVMTestAdapter<'a> {
})
.map_err(|e| {
anyhow!(
"Unable to publish module '{}'. Got VMError: {:?}",
"Unable to publish module '{}'. Got VMError: {}",
module.self_id(),
e
format_vm_error(&e)
)
})
}
@@ -136,7 +152,12 @@ impl<'a> MoveTestAdapter<'a> for SimpleVMTestAdapter<'a> {
self.perform_session_action(gas_budget, |session, gas_status| {
session.execute_script(script_bytes, type_args, args, signers, gas_status)
})
.map_err(|e| anyhow!("Script execution failed with VMError: {:?}", e))
.map_err(|e| {
anyhow!(
"Script execution failed with VMError: {}",
format_vm_error(&e)
)
})
}

fn call_function(
@@ -153,7 +174,12 @@ impl<'a> MoveTestAdapter<'a> for SimpleVMTestAdapter<'a> {
self.perform_session_action(gas_budget, |session, gas_status| {
session.execute_script_function(module, function, type_args, args, signers, gas_status)
})
.map_err(|e| anyhow!("Function execution failed with VMError: {:?}", e))
.map_err(|e| {
anyhow!(
"Function execution failed with VMError: {}",
format_vm_error(&e)
)
})
}

fn view_data(
@@ -184,6 +210,29 @@ impl<'a> MoveTestAdapter<'a> for SimpleVMTestAdapter<'a> {
}
}

pub fn format_vm_error(e: &VMError) -> String {
let location_string = match e.location() {
Location::Undefined => "undefined".to_owned(),
Location::Script => "script".to_owned(),
Location::Module(id) => format!("0x{}::{}", id.address().short_str_lossless(), id.name()),
};
format!(
"{{
major_status: {major_status:?},
sub_status: {sub_status:?},
location: {location_string},
indices: {indices:?},
offsets: {offsets:?},
}}",
major_status = e.major_status(),
sub_status = e.sub_status(),
location_string = location_string,
// TODO maybe include source map info?
indices = e.indices(),
offsets = e.offsets(),
)
}

impl<'a> SimpleVMTestAdapter<'a> {
fn perform_session_action(
&mut self,
Original file line number Diff line number Diff line change
@@ -4,7 +4,13 @@ task 3 'view'. lines 13-15:
[No Resource Exists]

task 5 'run'. lines 37-37:
Error: Function execution failed with VMError: VMError { major_status: ABORTED, sub_status: Some(0), message: Some("0x00000000000000000000000000000042::N::ex at offset 1"), location: Module(ModuleId { address: 00000000000000000000000000000042, name: Identifier("N") }), indices: [], offsets: [(FunctionDefinitionIndex(0), 1)] }
Error: Function execution failed with VMError: {
major_status: ABORTED,
sub_status: Some(0),
location: 0x42::N,
indices: [],
offsets: [(FunctionDefinitionIndex(0), 1)],
}

task 7 'view'. lines 47-49:
key 0x42::N::R<U64> {
1 change: 1 addition & 0 deletions x.toml
Original file line number Diff line number Diff line change
@@ -179,6 +179,7 @@ members = [

"bytecode-interpreter-testsuite",
"bytecode-verifier-tests",
"bytecode-verifier-transactional-tests",
"cli",
"cluster-test",
"compatibility-test",

0 comments on commit e2b392f

Please sign in to comment.