diff --git a/Cargo.toml b/Cargo.toml index f8ca62a101..1f5c472f95 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,11 +43,12 @@ num-bigint = "0.4.0" sha2 = "0.9.3" -better_any = "0.1.1" # impl Traits for Mutex/RwLock, may not be a problem if not used; +acid_io = { version = "0.1.0", features = ["alloc"] } # std::error::Error anyhow = "1.0.52" +better_any = "0.1.1" # impl Traits for Mutex/RwLock, may not be a problem if not used; fail = "0.4.0" [profile.bench] debug = true diff --git a/language/move-binary-format/Cargo.toml b/language/move-binary-format/Cargo.toml index e40a19dc87..fa127b72ab 100644 --- a/language/move-binary-format/Cargo.toml +++ b/language/move-binary-format/Cargo.toml @@ -16,6 +16,7 @@ variant_count.workspace = true move-core-types = { path = "../move-core/types" } serde.workspace = true hashbrown.workspace = true +acid_io.workspace = true arbitrary = { version = "1.1.7", optional = true, features = ["derive"] } proptest = { version = "1.0.0", optional = true } proptest-derive = { version = "0.3.0", optional = true } diff --git a/language/move-binary-format/src/deserializer.rs b/language/move-binary-format/src/deserializer.rs index bd9488fbcd..bc70c51def 100644 --- a/language/move-binary-format/src/deserializer.rs +++ b/language/move-binary-format/src/deserializer.rs @@ -12,7 +12,7 @@ use move_core_types::{ account_address::AccountAddress, identifier::Identifier, metadata::Metadata, state::VMState, vm_status::StatusCode, }; -use std::io::Read; +use acid_io::Read; impl CompiledScript { /// Deserializes a &[u8] slice into a `CompiledScript` instance. @@ -949,7 +949,7 @@ fn load_signature_tokens(cursor: &mut VersionedCursor) -> BinaryLoaderResult, + cursor: acid_io::Cursor<&[u8]>, ) -> BinaryLoaderResult { load_signature_token(&mut VersionedCursor::new_for_test(VERSION_MAX, cursor)) } diff --git a/language/move-binary-format/src/file_format_common.rs b/language/move-binary-format/src/file_format_common.rs index deee4364d8..33b3ebfd9b 100644 --- a/language/move-binary-format/src/file_format_common.rs +++ b/language/move-binary-format/src/file_format_common.rs @@ -13,9 +13,9 @@ //! It's used to compress mostly indexes into the main binary tables. use crate::file_format::Bytecode; use crate::no_std::prelude::*; +use acid_io::{Cursor, Read}; use anyhow::{bail, Result}; use core::mem::size_of; -use std::io::{Cursor, Read}; /// Constant values for the binary format header. /// @@ -338,13 +338,17 @@ pub(crate) fn write_u256( pub fn read_u8(cursor: &mut Cursor<&[u8]>) -> Result { let mut buf = [0; 1]; - cursor.read_exact(&mut buf)?; + cursor + .read_exact(&mut buf) + .map_err(|e| anyhow::format_err!("{e}"))?; Ok(buf[0]) } pub fn read_u32(cursor: &mut Cursor<&[u8]>) -> Result { let mut buf = [0; 4]; - cursor.read_exact(&mut buf)?; + cursor + .read_exact(&mut buf) + .map_err(|e| anyhow::format_err!("{e}"))?; Ok(u32::from_le_bytes(buf)) } @@ -413,8 +417,8 @@ pub const VERSION_MIN: u32 = VERSION_5; pub(crate) mod versioned_data { use crate::{errors::*, file_format_common::*}; + use acid_io::{Cursor, Read}; use move_core_types::vm_status::StatusCode; - use std::io::{Cursor, Read}; pub struct VersionedBinary<'a> { version: u32, binary: &'a [u8], @@ -535,7 +539,7 @@ pub(crate) mod versioned_data { } impl<'a> Read for VersionedCursor<'a> { - fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + fn read(&mut self, buf: &mut [u8]) -> acid_io::Result { self.cursor.read(buf) } } diff --git a/language/move-borrow-graph/src/graph.rs b/language/move-borrow-graph/src/graph.rs index 81d2752597..a1c29ce1b0 100644 --- a/language/move-borrow-graph/src/graph.rs +++ b/language/move-borrow-graph/src/graph.rs @@ -4,7 +4,7 @@ use crate::{ no_std::prelude::*, - paths::{self, Path, PathSlice}, + paths::{self, Path}, references::*, }; use alloc::collections::{BTreeMap, BTreeSet}; diff --git a/language/move-bytecode-verifier/Cargo.toml b/language/move-bytecode-verifier/Cargo.toml index 0e42dec928..033575d2d3 100644 --- a/language/move-bytecode-verifier/Cargo.toml +++ b/language/move-bytecode-verifier/Cargo.toml @@ -21,7 +21,7 @@ move-core-types = { path = "../move-core/types" } [dev-dependencies] hex-literal = "0.3.4" -invalid-mutations = { path = "invalid-mutations" } +#invalid-mutations = { path = "invalid-mutations" } [features] default = [] diff --git a/language/move-bytecode-verifier/fuzz/.gitignore b/language/move-bytecode-verifier/fuzz/.gitignore deleted file mode 100644 index a0925114d6..0000000000 --- a/language/move-bytecode-verifier/fuzz/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -target -corpus -artifacts diff --git a/language/move-bytecode-verifier/fuzz/Cargo.toml b/language/move-bytecode-verifier/fuzz/Cargo.toml deleted file mode 100644 index 90c2a406bd..0000000000 --- a/language/move-bytecode-verifier/fuzz/Cargo.toml +++ /dev/null @@ -1,39 +0,0 @@ -[package] -name = "bytecode-verifier-libfuzzer" -version = "0.0.0" -authors = ["Diem Association "] -license = "Apache-2.0" -publish = false -edition = "2018" - -[package.metadata] -cargo-fuzz = true - -[dependencies] -libfuzzer-sys = "0.4" -arbitrary = "1.1.7" -move-bytecode-verifier = { path = "../" } -move-core-types = { path = "../../move-core/types", features = ["fuzzing"] } -move-binary-format = { path = "../../move-binary-format", features = ["fuzzing"] } - -# Prevent this from interfering with workspaces -#[workspace] -#members = ["."] - -[[bin]] -name = "code_unit" -path = "fuzz_targets/code_unit.rs" -test = false -doc = false - -[[bin]] -name = "compiled_module" -path = "fuzz_targets/compiled_module.rs" -test = false -doc = false - -[[bin]] -name = "mixed" -path = "fuzz_targets/mixed.rs" -test = false -doc = false diff --git a/language/move-bytecode-verifier/fuzz/README.md b/language/move-bytecode-verifier/fuzz/README.md deleted file mode 100644 index 633a4797a4..0000000000 --- a/language/move-bytecode-verifier/fuzz/README.md +++ /dev/null @@ -1,4 +0,0 @@ -See the [Rust fuzzing book](https://rust-fuzz.github.io/book/) -for how to use the fuzz targets in this directory. Notice that -`cargo +nightly fuzz run ` need to be executed in the parent -directory; nightly is required. diff --git a/language/move-bytecode-verifier/fuzz/fuzz_targets/code_unit.rs b/language/move-bytecode-verifier/fuzz/fuzz_targets/code_unit.rs deleted file mode 100644 index 32d4cb8ac5..0000000000 --- a/language/move-bytecode-verifier/fuzz/fuzz_targets/code_unit.rs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) The Move Contributors -// SPDX-License-Identifier: Apache-2.0 - -#![no_main] -use move_binary_format::file_format::{ - empty_module, AbilitySet, CodeUnit, Constant, FieldDefinition, FunctionDefinition, - FunctionHandle, FunctionHandleIndex, IdentifierIndex, ModuleHandleIndex, Signature, - SignatureIndex, - SignatureToken::{Address, Bool, U128, U64}, - StructDefinition, StructFieldInformation, StructHandle, StructHandleIndex, TypeSignature, - Visibility, -}; -use move_core_types::{account_address::AccountAddress, identifier::Identifier}; -use std::str::FromStr; - -use libfuzzer_sys::fuzz_target; - -fuzz_target!(|code_unit: CodeUnit| { - let mut module = empty_module(); - module.version = 5; - - module.struct_handles.push(StructHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(1), - abilities: AbilitySet::ALL, - type_parameters: vec![], - }); - - let fun_handle = FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(2), - parameters: SignatureIndex(0), - return_: SignatureIndex(1), - type_parameters: vec![], - }; - - module.function_handles.push(fun_handle); - - module.signatures.pop(); - module.signatures.push(Signature(vec![ - Address, U64, Address, Address, U128, Address, U64, U64, U64, - ])); - module.signatures.push(Signature(vec![])); - module - .signatures - .push(Signature(vec![Address, Bool, Address])); - - module.identifiers.extend( - vec![ - Identifier::from_str("zf_hello_world").unwrap(), - Identifier::from_str("awldFnU18mlDKQfh6qNfBGx8X").unwrap(), - Identifier::from_str("aQPwJNHyAHpvJ").unwrap(), - Identifier::from_str("aT7ZphKTrKcYCwCebJySrmrKlckmnL5").unwrap(), - Identifier::from_str("arYpsFa2fvrpPJ").unwrap(), - ] - .into_iter(), - ); - module.address_identifiers.push(AccountAddress::random()); - - module.constant_pool.push(Constant { - type_: Address, - data: AccountAddress::ZERO.into_bytes().to_vec(), - }); - - module.struct_defs.push(StructDefinition { - struct_handle: StructHandleIndex(0), - field_information: StructFieldInformation::Declared(vec![FieldDefinition { - name: IdentifierIndex::new(3), - signature: TypeSignature(Address), - }]), - }); - - let fun_def = FunctionDefinition { - code: Some(code_unit), - function: FunctionHandleIndex(0), - visibility: Visibility::Public, - is_entry: false, - acquires_global_resources: vec![], - }; - - module.function_defs.push(fun_def); - let _ = move_bytecode_verifier::verify_module(&module); -}); diff --git a/language/move-bytecode-verifier/fuzz/fuzz_targets/compiled_module.rs b/language/move-bytecode-verifier/fuzz/fuzz_targets/compiled_module.rs deleted file mode 100644 index ba077a820d..0000000000 --- a/language/move-bytecode-verifier/fuzz/fuzz_targets/compiled_module.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) The Move Contributors -// SPDX-License-Identifier: Apache-2.0 - -#![no_main] -use libfuzzer_sys::fuzz_target; -use move_binary_format::file_format::CompiledModule; - -fuzz_target!(|module: CompiledModule| { - let _ = move_bytecode_verifier::verify_module(&module); -}); diff --git a/language/move-bytecode-verifier/fuzz/fuzz_targets/mixed.rs b/language/move-bytecode-verifier/fuzz/fuzz_targets/mixed.rs deleted file mode 100644 index 35df4a5f2f..0000000000 --- a/language/move-bytecode-verifier/fuzz/fuzz_targets/mixed.rs +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) The Move Contributors -// SPDX-License-Identifier: Apache-2.0 - -#![no_main] -use move_binary_format::file_format::{ - empty_module, AbilitySet, Bytecode, CodeUnit, Constant, FieldDefinition, FunctionDefinition, - FunctionHandle, FunctionHandleIndex, IdentifierIndex, ModuleHandleIndex, Signature, - SignatureIndex, SignatureToken, - SignatureToken::{Address, Bool}, - StructDefinition, StructFieldInformation, StructHandle, StructHandleIndex, TypeSignature, - Visibility, -}; -use move_core_types::{account_address::AccountAddress, identifier::Identifier}; -use std::str::FromStr; - -use arbitrary::Arbitrary; -use libfuzzer_sys::fuzz_target; - -#[derive(Arbitrary, Debug)] -struct Mixed { - code: Vec, - abilities: AbilitySet, - param_types: Vec, - return_type: Option, -} - -fuzz_target!(|mix: Mixed| { - let mut module = empty_module(); - module.version = 5; - - module.struct_handles.push(StructHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(1), - abilities: mix.abilities, - type_parameters: vec![], - }); - - let fun_handle = FunctionHandle { - module: ModuleHandleIndex(0), - name: IdentifierIndex(2), - parameters: SignatureIndex(0), - return_: SignatureIndex(1), - type_parameters: vec![], - }; - - module.function_handles.push(fun_handle); - - module.signatures.pop(); - module.signatures.push(Signature(mix.param_types)); - module.signatures.push(Signature( - mix.return_type.map(|s| vec![s]).unwrap_or_default(), - )); - module - .signatures - .push(Signature(vec![Address, Bool, Address])); - - module.identifiers.extend( - vec![ - Identifier::from_str("zf_hello_world").unwrap(), - Identifier::from_str("awldFnU18mlDKQfh6qNfBGx8X").unwrap(), - Identifier::from_str("aQPwJNHyAHpvJ").unwrap(), - Identifier::from_str("aT7ZphKTrKcYCwCebJySrmrKlckmnL5").unwrap(), - Identifier::from_str("arYpsFa2fvrpPJ").unwrap(), - ] - .into_iter(), - ); - module.address_identifiers.push(AccountAddress::random()); - - module.constant_pool.push(Constant { - type_: Address, - data: AccountAddress::ZERO.into_bytes().to_vec(), - }); - - module.struct_defs.push(StructDefinition { - struct_handle: StructHandleIndex(0), - field_information: StructFieldInformation::Declared(vec![FieldDefinition { - name: IdentifierIndex::new(3), - signature: TypeSignature(Address), - }]), - }); - - let code_unit = CodeUnit { - code: mix.code, - locals: SignatureIndex(0), - }; - - let fun_def = FunctionDefinition { - code: Some(code_unit), - function: FunctionHandleIndex(0), - visibility: Visibility::Public, - is_entry: false, - acquires_global_resources: vec![], - }; - - module.function_defs.push(fun_def); - let _ = move_bytecode_verifier::verify_module(&module); -}); diff --git a/language/move-bytecode-verifier/invalid-mutations/Cargo.toml b/language/move-bytecode-verifier/invalid-mutations/Cargo.toml deleted file mode 100644 index ed46af714c..0000000000 --- a/language/move-bytecode-verifier/invalid-mutations/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "invalid-mutations" -version = "0.1.0" -edition = "2021" -authors = ["Diem Association "] -description = "Diem invalid mutations" -repository = "https://github.com/diem/diem" -homepage = "https://diem.com" -license = "Apache-2.0" -publish = false - -[dependencies] -move-core-types = { path = "../../move-core/types" } -move-binary-format = { path = "../../move-binary-format" } -proptest = "1.0.0" - -[features] -default = [] diff --git a/language/move-bytecode-verifier/invalid-mutations/src/bounds.rs b/language/move-bytecode-verifier/invalid-mutations/src/bounds.rs deleted file mode 100644 index b4d31c2011..0000000000 --- a/language/move-bytecode-verifier/invalid-mutations/src/bounds.rs +++ /dev/null @@ -1,364 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// SPDX-License-Identifier: Apache-2.0 - -use move_binary_format::{ - errors::{bounds_error, PartialVMError}, - file_format::{ - AddressIdentifierIndex, CompiledModule, FunctionHandleIndex, IdentifierIndex, - ModuleHandleIndex, SignatureIndex, StructDefinitionIndex, StructHandleIndex, TableIndex, - }, - internals::ModuleIndex, - views::{ModuleView, SignatureTokenView}, - IndexKind, -}; -use move_core_types::vm_status::StatusCode; -use proptest::{ - prelude::*, - sample::{self, Index as PropIndex}, -}; -use std::collections::BTreeMap; - -mod code_unit; -pub use code_unit::{ApplyCodeUnitBoundsContext, CodeUnitBoundsMutation}; -use move_binary_format::file_format::SignatureToken; - -/// Represents the number of pointers that exist out from a node of a particular kind. -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub enum PointerKind { - /// Exactly one pointer out with this index kind as its destination. - One(IndexKind), - /// Zero or one pointer out with this index kind as its destination. Like the `?` operator in - /// regular expressions. - Optional(IndexKind), - /// Zero or more pointers out with this index kind as its destination. Like the `*` operator - /// in regular expressions. - Star(IndexKind), -} - -impl PointerKind { - /// A list of what pointers (indexes) exist out from a particular kind of node within the - /// module. - /// - /// The only special case is `FunctionDefinition`, which contains a `CodeUnit` that can contain - /// one of several kinds of pointers out. That is not represented in this table. - #[inline] - pub fn pointers_from(src_kind: IndexKind) -> &'static [PointerKind] { - use IndexKind::*; - use PointerKind::*; - - match src_kind { - ModuleHandle => &[One(AddressIdentifier), One(Identifier)], - StructHandle => &[One(ModuleHandle), One(Identifier)], - FunctionHandle => &[ - One(ModuleHandle), - One(Identifier), - One(Signature), - One(Signature), - ], - StructDefinition => &[One(StructHandle), Star(StructHandle)], - FunctionDefinition => &[One(FunctionHandle), One(Signature)], - FriendDeclaration => &[One(AddressIdentifier), One(Identifier)], - Signature => &[Star(StructHandle)], - FieldHandle => &[One(StructDefinition)], - _ => &[], - } - } - - #[inline] - pub fn to_index_kind(self) -> IndexKind { - match self { - PointerKind::One(idx) | PointerKind::Optional(idx) | PointerKind::Star(idx) => idx, - } - } -} - -pub static VALID_POINTER_SRCS: &[IndexKind] = &[ - IndexKind::ModuleHandle, - IndexKind::StructHandle, - IndexKind::FunctionHandle, - IndexKind::FieldHandle, - IndexKind::StructDefinition, - IndexKind::FunctionDefinition, - IndexKind::FriendDeclaration, - IndexKind::Signature, -]; - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn pointer_kind_sanity() { - for variant in IndexKind::variants() { - if VALID_POINTER_SRCS.iter().any(|x| x == variant) { - assert!( - !PointerKind::pointers_from(*variant).is_empty(), - "expected variant {:?} to be a valid pointer source", - variant, - ); - } else { - assert!( - PointerKind::pointers_from(*variant).is_empty(), - "expected variant {:?} to not be a valid pointer source", - variant, - ); - } - } - } -} - -/// Represents a single mutation to a `CompiledModule` to produce an out-of-bounds situation. -/// -/// Use `OutOfBoundsMutation::strategy()` to generate them, preferably using `Vec` to generate -/// many at a time. Then use `ApplyOutOfBoundsContext` to apply those mutations. -#[derive(Debug)] -pub struct OutOfBoundsMutation { - src_kind: IndexKind, - src_idx: PropIndex, - dst_kind: IndexKind, - offset: usize, -} - -impl OutOfBoundsMutation { - pub fn strategy() -> impl Strategy { - ( - Self::src_kind_strategy(), - any::(), - any::(), - 0..16_usize, - ) - .prop_map(|(src_kind, src_idx, dst_kind_idx, offset)| { - let dst_kind = Self::dst_kind(src_kind, dst_kind_idx); - Self { - src_kind, - src_idx, - dst_kind, - offset, - } - }) - } - - // Not all source kinds can be made to be out of bounds (e.g. inherent types can't.) - fn src_kind_strategy() -> impl Strategy { - sample::select(VALID_POINTER_SRCS) - } - - fn dst_kind(src_kind: IndexKind, dst_kind_idx: PropIndex) -> IndexKind { - dst_kind_idx - .get(PointerKind::pointers_from(src_kind)) - .to_index_kind() - } -} - -/// This is used for source indexing, to work with pick_slice_idxs. -impl AsRef for OutOfBoundsMutation { - #[inline] - fn as_ref(&self) -> &PropIndex { - &self.src_idx - } -} - -pub struct ApplyOutOfBoundsContext { - module: CompiledModule, - // This is an Option because it gets moved out in apply before apply_one is called. Rust - // doesn't let you call another con-consuming method after a partial move out. - mutations: Option>, - - // Some precomputations done for signatures. - sig_structs: Vec<(SignatureIndex, usize)>, -} - -impl ApplyOutOfBoundsContext { - pub fn new(module: CompiledModule, mutations: Vec) -> Self { - let sig_structs: Vec<_> = Self::sig_structs(&module).collect(); - - Self { - module, - mutations: Some(mutations), - sig_structs, - } - } - - pub fn apply(mut self) -> (CompiledModule, Vec) { - // This is a map from (source kind, dest kind) to the actual mutations -- this is done to - // figure out how many mutations to do for a particular pair, which is required for - // pick_slice_idxs below. - let mut mutation_map = BTreeMap::new(); - for mutation in self - .mutations - .take() - .expect("mutations should always be present") - { - mutation_map - .entry((mutation.src_kind, mutation.dst_kind)) - .or_insert_with(Vec::new) - .push(mutation); - } - - let mut results = vec![]; - - for ((src_kind, dst_kind), mutations) in mutation_map { - // It would be cool to use an iterator here, if someone could figure out exactly how - // to get the lifetimes right :) - results.extend(self.apply_one(src_kind, dst_kind, mutations)); - } - (self.module, results) - } - - fn apply_one( - &mut self, - src_kind: IndexKind, - dst_kind: IndexKind, - mutations: Vec, - ) -> Vec { - let src_count = match src_kind { - IndexKind::Signature => self.sig_structs.len(), - // For the other sorts it's always possible to change an index. - src_kind => self.module.kind_count(src_kind), - }; - // Any signature can be a destination, not just the ones that have structs in them. - let dst_count = self.module.kind_count(dst_kind); - let to_mutate = crate::helpers::pick_slice_idxs(src_count, &mutations); - - mutations - .iter() - .zip(to_mutate) - .map(move |(mutation, src_idx)| { - self.set_index( - src_kind, - src_idx, - dst_kind, - dst_count, - (dst_count + mutation.offset) as TableIndex, - ) - }) - .collect() - } - - /// Sets the particular index in the table - /// - /// For example, with `src_kind` set to `ModuleHandle` and `dst_kind` set to `AddressPool`, - /// this will set self.module_handles[src_idx].address to new_idx. - /// - /// This is mainly used for test generation. - fn set_index( - &mut self, - src_kind: IndexKind, - src_idx: usize, - dst_kind: IndexKind, - dst_count: usize, - new_idx: TableIndex, - ) -> PartialVMError { - use IndexKind::*; - - // These are default values, but some of the match arms below mutate them. - let mut src_idx = src_idx; - let err = bounds_error( - StatusCode::INDEX_OUT_OF_BOUNDS, - dst_kind, - new_idx, - dst_count, - ); - - // A dynamic type system would be able to express this next block of code far more - // concisely. A static type system would require some sort of complicated dependent type - // structure that Rust doesn't have. As things stand today, every possible case needs to - // be listed out. - - match (src_kind, dst_kind) { - (ModuleHandle, AddressIdentifier) => { - self.module.module_handles[src_idx].address = AddressIdentifierIndex(new_idx) - } - (ModuleHandle, Identifier) => { - self.module.module_handles[src_idx].name = IdentifierIndex(new_idx) - } - (StructHandle, ModuleHandle) => { - self.module.struct_handles[src_idx].module = ModuleHandleIndex(new_idx) - } - (StructHandle, Identifier) => { - self.module.struct_handles[src_idx].name = IdentifierIndex(new_idx) - } - (FunctionHandle, ModuleHandle) => { - self.module.function_handles[src_idx].module = ModuleHandleIndex(new_idx) - } - (FunctionHandle, Identifier) => { - self.module.function_handles[src_idx].name = IdentifierIndex(new_idx) - } - (FunctionHandle, Signature) => { - self.module.function_handles[src_idx].parameters = SignatureIndex(new_idx) - } - (StructDefinition, StructHandle) => { - self.module.struct_defs[src_idx].struct_handle = StructHandleIndex(new_idx) - } - (FunctionDefinition, FunctionHandle) => { - self.module.function_defs[src_idx].function = FunctionHandleIndex(new_idx) - } - (FunctionDefinition, Signature) => { - self.module.function_defs[src_idx] - .code - .as_mut() - .unwrap() - .locals = SignatureIndex(new_idx) - } - (Signature, StructHandle) => { - let (actual_src_idx, arg_idx) = self.sig_structs[src_idx]; - src_idx = actual_src_idx.into_index(); - self.module.signatures[src_idx].0[arg_idx] - .debug_set_sh_idx(StructHandleIndex(new_idx)); - } - (FieldHandle, StructDefinition) => { - self.module.field_handles[src_idx].owner = StructDefinitionIndex(new_idx) - } - (FriendDeclaration, AddressIdentifier) => { - self.module.friend_decls[src_idx].address = AddressIdentifierIndex(new_idx) - } - (FriendDeclaration, Identifier) => { - self.module.friend_decls[src_idx].name = IdentifierIndex(new_idx) - } - _ => panic!("Invalid pointer kind: {:?} -> {:?}", src_kind, dst_kind), - } - - err.at_index(src_kind, src_idx as TableIndex) - } - - /// Returns the indexes of locals signatures that contain struct handles inside them. - fn sig_structs(module: &CompiledModule) -> impl Iterator + '_ { - let module_view = ModuleView::new(module); - module_view - .signatures() - .enumerate() - .flat_map(|(idx, signature)| { - let idx = SignatureIndex(idx as u16); - Self::find_struct_tokens(signature.tokens(), move |arg_idx| (idx, arg_idx)) - }) - } - - #[inline] - fn find_struct_tokens<'b, F, T>( - tokens: impl IntoIterator> + 'b, - map_fn: F, - ) -> impl Iterator + 'b - where - F: Fn(usize) -> T + 'b, - { - tokens - .into_iter() - .enumerate() - .filter_map(move |(arg_idx, token)| { - struct_handle(token.signature_token()).map(|_| map_fn(arg_idx)) - }) - } -} - -fn struct_handle(token: &SignatureToken) -> Option { - use SignatureToken::*; - - match token { - Struct(sh_idx) => Some(*sh_idx), - StructInstantiation(sh_idx, _) => Some(*sh_idx), - Reference(token) | MutableReference(token) => struct_handle(token), - Bool | U8 | U16 | U32 | U64 | U128 | U256 | Address | Signer | Vector(_) - | TypeParameter(_) => None, - } -} diff --git a/language/move-bytecode-verifier/invalid-mutations/src/bounds/code_unit.rs b/language/move-bytecode-verifier/invalid-mutations/src/bounds/code_unit.rs deleted file mode 100644 index 18085317dc..0000000000 --- a/language/move-bytecode-verifier/invalid-mutations/src/bounds/code_unit.rs +++ /dev/null @@ -1,547 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// SPDX-License-Identifier: Apache-2.0 - -use move_binary_format::{ - errors::{offset_out_of_bounds, PartialVMError}, - file_format::{ - Bytecode, CodeOffset, CompiledModule, ConstantPoolIndex, FieldHandleIndex, - FieldInstantiationIndex, FunctionDefinitionIndex, FunctionHandleIndex, - FunctionInstantiationIndex, LocalIndex, SignatureIndex, StructDefInstantiationIndex, - StructDefinitionIndex, TableIndex, - }, - internals::ModuleIndex, - IndexKind, -}; -use move_core_types::vm_status::StatusCode; -use proptest::{prelude::*, sample::Index as PropIndex}; -use std::collections::BTreeMap; - -/// Represents a single mutation onto a code unit to make it out of bounds. -#[derive(Debug)] -pub struct CodeUnitBoundsMutation { - function_def: PropIndex, - bytecode: PropIndex, - offset: usize, -} - -impl CodeUnitBoundsMutation { - pub fn strategy() -> impl Strategy { - (any::(), any::(), 0..16_usize).prop_map( - |(function_def, bytecode, offset)| Self { - function_def, - bytecode, - offset, - }, - ) - } -} - -impl AsRef for CodeUnitBoundsMutation { - #[inline] - fn as_ref(&self) -> &PropIndex { - &self.bytecode - } -} - -pub struct ApplyCodeUnitBoundsContext<'a> { - module: &'a mut CompiledModule, - // This is so apply_one can be called after mutations has been iterated on. - mutations: Option>, -} - -macro_rules! new_bytecode { - ($dst_len:expr, $fidx:expr, $bcidx:expr, $offset:expr, $kind:ident, $bytecode_ident:tt) => {{ - let dst_len: usize = $dst_len; - let new_idx: usize = dst_len + $offset; - ( - $bytecode_ident($kind::new(new_idx as TableIndex)), - offset_out_of_bounds( - StatusCode::INDEX_OUT_OF_BOUNDS, - $kind::KIND, - new_idx, - dst_len, - $fidx, - $bcidx as CodeOffset, - ), - ) - }}; - - ($dst_len:expr, $fidx:expr, $bcidx:expr, $offset:expr, $kind:ident, $bytecode_ident:tt, $($others:expr),+) => {{ - let dst_len: usize = $dst_len; - let new_idx: usize = dst_len + $offset; - ( - $bytecode_ident($kind::new(new_idx as TableIndex), $($others),+), - offset_out_of_bounds( - StatusCode::INDEX_OUT_OF_BOUNDS, - $kind::KIND, - new_idx, - dst_len, - $fidx, - $bcidx as CodeOffset, - ), - ) - }}; -} - -macro_rules! struct_bytecode { - ($dst_len: expr, $fidx:expr, $bcidx: expr, $offset: expr, $idx_type: ident, $bytecode_ident: tt) => {{ - let dst_len = $dst_len; - let new_idx = dst_len + $offset; - ( - $bytecode_ident($idx_type::new(new_idx as TableIndex)), - offset_out_of_bounds( - StatusCode::INDEX_OUT_OF_BOUNDS, - $idx_type::KIND, - new_idx, - dst_len, - $fidx, - $bcidx as CodeOffset, - ), - ) - }}; -} - -macro_rules! code_bytecode { - ($code_len: expr, $fidx:expr, $bcidx: expr, $offset: expr, $bytecode_ident: tt) => {{ - let code_len = $code_len; - let new_idx = code_len + $offset; - ( - $bytecode_ident(new_idx as CodeOffset), - offset_out_of_bounds( - StatusCode::INDEX_OUT_OF_BOUNDS, - IndexKind::CodeDefinition, - new_idx, - code_len, - $fidx, - $bcidx as CodeOffset, - ), - ) - }}; -} - -macro_rules! locals_bytecode { - ($locals_len: expr, $fidx:expr, $bcidx: expr, $offset: expr, $bytecode_ident: tt) => {{ - let locals_len = $locals_len; - let new_idx = locals_len + $offset; - ( - $bytecode_ident(new_idx as LocalIndex), - offset_out_of_bounds( - StatusCode::INDEX_OUT_OF_BOUNDS, - IndexKind::LocalPool, - new_idx, - locals_len, - $fidx, - $bcidx as CodeOffset, - ), - ) - }}; -} - -impl<'a> ApplyCodeUnitBoundsContext<'a> { - pub fn new(module: &'a mut CompiledModule, mutations: Vec) -> Self { - Self { - module, - mutations: Some(mutations), - } - } - - pub fn apply(mut self) -> Vec { - let function_def_len = self.module.function_defs.len(); - - let mut mutation_map = BTreeMap::new(); - for mutation in self - .mutations - .take() - .expect("mutations should always be present") - { - let picked_idx = mutation.function_def.index(function_def_len); - mutation_map - .entry(picked_idx) - .or_insert_with(Vec::new) - .push(mutation); - } - - let mut results = vec![]; - - for (idx, mutations) in mutation_map { - results.extend(self.apply_one(idx, mutations)); - } - results - } - - fn apply_one( - &mut self, - fidx: usize, - mutations: Vec, - ) -> Vec { - // For this function def, find all the places where a bounds mutation can be applied. - let func_def = &mut self.module.function_defs[fidx]; - let current_fdef = FunctionDefinitionIndex(fidx as TableIndex); - let func_handle = &self.module.function_handles[func_def.function.into_index()]; - let code = func_def.code.as_mut().unwrap(); - let locals_len = self.module.signatures[func_handle.parameters.into_index()].len() - + self.module.signatures[code.locals.into_index()].len(); - let code = &mut code.code; - let code_len = code.len(); - - let interesting_offsets: Vec = (0..code.len()) - .filter(|bytecode_idx| is_interesting(&code[*bytecode_idx])) - .collect(); - let to_mutate = crate::helpers::pick_slice_idxs(interesting_offsets.len(), &mutations); - - // These have to be computed upfront because self.module is being mutated below. - let constant_pool_len = self.module.constant_pool.len(); - let function_handles_len = self.module.function_handles.len(); - let field_handle_len = self.module.field_handles.len(); - let struct_defs_len = self.module.struct_defs.len(); - let struct_inst_len = self.module.struct_def_instantiations.len(); - let function_inst_len = self.module.function_instantiations.len(); - let field_inst_len = self.module.field_instantiations.len(); - let signature_pool_len = self.module.signatures.len(); - - mutations - .iter() - .zip(to_mutate) - .map(|(mutation, interesting_offsets_idx)| { - let bytecode_idx = interesting_offsets[interesting_offsets_idx]; - let offset = mutation.offset; - use Bytecode::*; - - let (new_bytecode, err) = match code[bytecode_idx] { - LdConst(_) => new_bytecode!( - constant_pool_len, - current_fdef, - bytecode_idx, - offset, - ConstantPoolIndex, - LdConst - ), - ImmBorrowField(_) => new_bytecode!( - field_handle_len, - current_fdef, - bytecode_idx, - offset, - FieldHandleIndex, - ImmBorrowField - ), - ImmBorrowFieldGeneric(_) => new_bytecode!( - field_inst_len, - current_fdef, - bytecode_idx, - offset, - FieldInstantiationIndex, - ImmBorrowFieldGeneric - ), - MutBorrowField(_) => new_bytecode!( - field_handle_len, - current_fdef, - bytecode_idx, - offset, - FieldHandleIndex, - MutBorrowField - ), - MutBorrowFieldGeneric(_) => new_bytecode!( - field_inst_len, - current_fdef, - bytecode_idx, - offset, - FieldInstantiationIndex, - MutBorrowFieldGeneric - ), - Call(_) => struct_bytecode!( - function_handles_len, - current_fdef, - bytecode_idx, - offset, - FunctionHandleIndex, - Call - ), - CallGeneric(_) => struct_bytecode!( - function_inst_len, - current_fdef, - bytecode_idx, - offset, - FunctionInstantiationIndex, - CallGeneric - ), - Pack(_) => struct_bytecode!( - struct_defs_len, - current_fdef, - bytecode_idx, - offset, - StructDefinitionIndex, - Pack - ), - PackGeneric(_) => struct_bytecode!( - struct_inst_len, - current_fdef, - bytecode_idx, - offset, - StructDefInstantiationIndex, - PackGeneric - ), - Unpack(_) => struct_bytecode!( - struct_defs_len, - current_fdef, - bytecode_idx, - offset, - StructDefinitionIndex, - Unpack - ), - UnpackGeneric(_) => struct_bytecode!( - struct_inst_len, - current_fdef, - bytecode_idx, - offset, - StructDefInstantiationIndex, - UnpackGeneric - ), - Exists(_) => struct_bytecode!( - struct_defs_len, - current_fdef, - bytecode_idx, - offset, - StructDefinitionIndex, - Exists - ), - ExistsGeneric(_) => struct_bytecode!( - struct_inst_len, - current_fdef, - bytecode_idx, - offset, - StructDefInstantiationIndex, - ExistsGeneric - ), - MutBorrowGlobal(_) => struct_bytecode!( - struct_defs_len, - current_fdef, - bytecode_idx, - offset, - StructDefinitionIndex, - MutBorrowGlobal - ), - MutBorrowGlobalGeneric(_) => struct_bytecode!( - struct_inst_len, - current_fdef, - bytecode_idx, - offset, - StructDefInstantiationIndex, - MutBorrowGlobalGeneric - ), - ImmBorrowGlobal(_) => struct_bytecode!( - struct_defs_len, - current_fdef, - bytecode_idx, - offset, - StructDefinitionIndex, - ImmBorrowGlobal - ), - ImmBorrowGlobalGeneric(_) => struct_bytecode!( - struct_inst_len, - current_fdef, - bytecode_idx, - offset, - StructDefInstantiationIndex, - ImmBorrowGlobalGeneric - ), - MoveFrom(_) => struct_bytecode!( - struct_defs_len, - current_fdef, - bytecode_idx, - offset, - StructDefinitionIndex, - MoveFrom - ), - MoveFromGeneric(_) => struct_bytecode!( - struct_inst_len, - current_fdef, - bytecode_idx, - offset, - StructDefInstantiationIndex, - MoveFromGeneric - ), - MoveTo(_) => struct_bytecode!( - struct_defs_len, - current_fdef, - bytecode_idx, - offset, - StructDefinitionIndex, - MoveTo - ), - MoveToGeneric(_) => struct_bytecode!( - struct_inst_len, - current_fdef, - bytecode_idx, - offset, - StructDefInstantiationIndex, - MoveToGeneric - ), - BrTrue(_) => { - code_bytecode!(code_len, current_fdef, bytecode_idx, offset, BrTrue) - } - BrFalse(_) => { - code_bytecode!(code_len, current_fdef, bytecode_idx, offset, BrFalse) - } - Branch(_) => { - code_bytecode!(code_len, current_fdef, bytecode_idx, offset, Branch) - } - CopyLoc(_) => { - locals_bytecode!(locals_len, current_fdef, bytecode_idx, offset, CopyLoc) - } - MoveLoc(_) => { - locals_bytecode!(locals_len, current_fdef, bytecode_idx, offset, MoveLoc) - } - StLoc(_) => { - locals_bytecode!(locals_len, current_fdef, bytecode_idx, offset, StLoc) - } - MutBorrowLoc(_) => locals_bytecode!( - locals_len, - current_fdef, - bytecode_idx, - offset, - MutBorrowLoc - ), - ImmBorrowLoc(_) => locals_bytecode!( - locals_len, - current_fdef, - bytecode_idx, - offset, - ImmBorrowLoc - ), - VecPack(_, num) => new_bytecode!( - signature_pool_len, - current_fdef, - bytecode_idx, - offset, - SignatureIndex, - VecPack, - num - ), - VecLen(_) => new_bytecode!( - signature_pool_len, - current_fdef, - bytecode_idx, - offset, - SignatureIndex, - VecLen - ), - VecImmBorrow(_) => new_bytecode!( - signature_pool_len, - current_fdef, - bytecode_idx, - offset, - SignatureIndex, - VecImmBorrow - ), - VecMutBorrow(_) => new_bytecode!( - signature_pool_len, - current_fdef, - bytecode_idx, - offset, - SignatureIndex, - VecMutBorrow - ), - VecPushBack(_) => new_bytecode!( - signature_pool_len, - current_fdef, - bytecode_idx, - offset, - SignatureIndex, - VecPushBack - ), - VecPopBack(_) => new_bytecode!( - signature_pool_len, - current_fdef, - bytecode_idx, - offset, - SignatureIndex, - VecPopBack - ), - VecUnpack(_, num) => new_bytecode!( - signature_pool_len, - current_fdef, - bytecode_idx, - offset, - SignatureIndex, - VecUnpack, - num - ), - VecSwap(_) => new_bytecode!( - signature_pool_len, - current_fdef, - bytecode_idx, - offset, - SignatureIndex, - VecSwap - ), - - // List out the other options explicitly so there's a compile error if a new - // bytecode gets added. - FreezeRef | Pop | Ret | LdU8(_) | LdU16(_) | LdU32(_) | LdU64(_) - | LdU128(_) | LdU256(_) | CastU8 | CastU16 | CastU32 | CastU64 | CastU128 - | CastU256 | LdTrue | LdFalse | ReadRef | WriteRef | Add | Sub | Mul | Mod - | Div | BitOr | BitAnd | Xor | Shl | Shr | Or | And | Not | Eq | Neq | Lt - | Gt | Le | Ge | Abort | Nop => { - panic!("Bytecode has no internal index: {:?}", code[bytecode_idx]) - } - }; - - code[bytecode_idx] = new_bytecode; - - err.at_index(IndexKind::FunctionDefinition, fidx as TableIndex) - }) - .collect() - } -} - -fn is_interesting(bytecode: &Bytecode) -> bool { - use Bytecode::*; - - match bytecode { - LdConst(_) - | ImmBorrowField(_) - | ImmBorrowFieldGeneric(_) - | MutBorrowField(_) - | MutBorrowFieldGeneric(_) - | Call(_) - | CallGeneric(_) - | Pack(_) - | PackGeneric(_) - | Unpack(_) - | UnpackGeneric(_) - | Exists(_) - | ExistsGeneric(_) - | MutBorrowGlobal(_) - | MutBorrowGlobalGeneric(_) - | ImmBorrowGlobal(_) - | ImmBorrowGlobalGeneric(_) - | MoveFrom(_) - | MoveFromGeneric(_) - | MoveTo(_) - | MoveToGeneric(_) - | BrTrue(_) - | BrFalse(_) - | Branch(_) - | CopyLoc(_) - | MoveLoc(_) - | StLoc(_) - | MutBorrowLoc(_) - | ImmBorrowLoc(_) - | VecPack(..) - | VecLen(_) - | VecImmBorrow(_) - | VecMutBorrow(_) - | VecPushBack(_) - | VecPopBack(_) - | VecUnpack(..) - | VecSwap(_) => true, - - // List out the other options explicitly so there's a compile error if a new - // bytecode gets added. - FreezeRef | Pop | Ret | LdU8(_) | LdU16(_) | LdU32(_) | LdU64(_) | LdU128(_) - | LdU256(_) | CastU8 | CastU16 | CastU32 | CastU64 | CastU128 | CastU256 | LdTrue - | LdFalse | ReadRef | WriteRef | Add | Sub | Mul | Mod | Div | BitOr | BitAnd | Xor - | Shl | Shr | Or | And | Not | Eq | Neq | Lt | Gt | Le | Ge | Abort | Nop => false, - } -} diff --git a/language/move-bytecode-verifier/invalid-mutations/src/helpers.rs b/language/move-bytecode-verifier/invalid-mutations/src/helpers.rs deleted file mode 100644 index c122d58c87..0000000000 --- a/language/move-bytecode-verifier/invalid-mutations/src/helpers.rs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// SPDX-License-Identifier: Apache-2.0 - -use proptest::sample::Index as PropIndex; -use std::{collections::BTreeSet, ops::Index as OpsIndex}; - -/// Given a maximum value `max` and a list of [`Index`](proptest::sample::Index) instances, picks -/// integers in the range `[0, max)` uniformly randomly and without duplication. -/// -/// If `indexes_len` is greater than `max`, all indexes will be returned. -/// -/// This function implements Robert Floyd's F2 algorithm for sampling without replacement. -pub(crate) fn pick_idxs(max: usize, indexes: &T, indexes_len: usize) -> Vec -where - T: OpsIndex + ?Sized, - P: AsRef, -{ - // See https://dl.acm.org/doi/10.1145/30401.315746 (the F2 algorithm) - // for a longer explanation. This is a variant that works with zero-indexing. - let mut selected = BTreeSet::new(); - let to_select = indexes_len.min(max); - for (iter_idx, choice) in ((max - to_select)..max).enumerate() { - // "RandInt(1, J)" in the original algorithm means a number between 1 - // and choice, both inclusive. `PropIndex::index` picks a number between 0 and - // whatever's passed in, with the latter exclusive. Pass in "+1" to ensure the same - // range of values is picked from. (This also ensures that if choice is 0 then `index` - // doesn't panic. - let idx = indexes[iter_idx].as_ref().index(choice + 1); - if !selected.insert(idx) { - selected.insert(choice); - } - } - selected.into_iter().collect() -} - -/// Given a maximum value `max` and a slice of [`Index`](proptest::sample::Index) instances, picks -/// integers in the range `[0, max)` uniformly randomly and without duplication. -/// -/// If the number of `Index` instances is greater than `max`, all indexes will be returned. -/// -/// This function implements Robert Floyd's F2 algorithm for sampling without replacement. -#[inline] -pub(crate) fn pick_slice_idxs(max: usize, indexes: &[impl AsRef]) -> Vec { - pick_idxs(max, indexes, indexes.len()) -} diff --git a/language/move-bytecode-verifier/invalid-mutations/src/lib.rs b/language/move-bytecode-verifier/invalid-mutations/src/lib.rs deleted file mode 100644 index d657424515..0000000000 --- a/language/move-bytecode-verifier/invalid-mutations/src/lib.rs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// SPDX-License-Identifier: Apache-2.0 - -#![forbid(unsafe_code)] - -pub mod bounds; -mod helpers; -pub mod signature; diff --git a/language/move-bytecode-verifier/invalid-mutations/src/signature.rs b/language/move-bytecode-verifier/invalid-mutations/src/signature.rs deleted file mode 100644 index 6181bf66d3..0000000000 --- a/language/move-bytecode-verifier/invalid-mutations/src/signature.rs +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) The Diem Core Contributors -// Copyright (c) The Move Contributors -// SPDX-License-Identifier: Apache-2.0 - -use move_binary_format::file_format::{ - CompiledModule, Signature, SignatureToken, StructFieldInformation, TypeSignature, -}; -use proptest::sample::Index as PropIndex; - -pub struct SignatureRefMutation<'a> { - module: &'a mut CompiledModule, - mutations: Vec<(PropIndex, PropIndex)>, -} - -impl<'a> SignatureRefMutation<'a> { - pub fn new(module: &'a mut CompiledModule, mutations: Vec<(PropIndex, PropIndex)>) -> Self { - Self { module, mutations } - } - - pub fn apply(self) -> bool { - if self.module.signatures.is_empty() { - return false; - } - let module = self.module; - let mut mutations = false; - for (s_idx, t_idx) in self.mutations { - let sig_idx = s_idx.index(module.signatures.len()); - let sig = &module.signatures[sig_idx]; - if sig.is_empty() { - continue; - } - let token_idx = t_idx.index(sig.len()); - let new_sig = mutate_sig(sig, token_idx); - module.signatures[sig_idx] = new_sig; - mutations = true; - } - mutations - } -} - -/// Context for applying a list of `FieldRefMutation` instances. -pub struct FieldRefMutation<'a> { - module: &'a mut CompiledModule, - mutations: Vec<(PropIndex, PropIndex)>, -} - -impl<'a> FieldRefMutation<'a> { - pub fn new(module: &'a mut CompiledModule, mutations: Vec<(PropIndex, PropIndex)>) -> Self { - Self { module, mutations } - } - - #[inline] - pub fn apply(self) -> bool { - if self.module.struct_defs.is_empty() { - return false; - } - let module = self.module; - let mut mutations = false; - for (s_idx, f_idx) in self.mutations { - let struct_idx = s_idx.index(module.struct_defs.len()); - let struct_def = &mut module.struct_defs[struct_idx]; - if let StructFieldInformation::Declared(fields) = &mut struct_def.field_information { - if fields.is_empty() { - continue; - } - let field_idx = f_idx.index(fields.len()); - let field_def = &mut fields[field_idx]; - let new_ty = mutate_field(&field_def.signature.0); - fields[field_idx].signature = TypeSignature(new_ty); - mutations = true; - } - } - mutations - } -} - -fn mutate_sig(sig: &Signature, token_idx: usize) -> Signature { - use SignatureToken::*; - - Signature( - sig.0 - .iter() - .enumerate() - .map(|(idx, token)| { - if idx == token_idx { - match &token { - Reference(_) | MutableReference(_) => Reference(Box::new(token.clone())), - _ => Reference(Box::new(Reference(Box::new(token.clone())))), - } - } else { - token.clone() - } - }) - .collect(), - ) -} - -fn mutate_field(token: &SignatureToken) -> SignatureToken { - SignatureToken::Reference(Box::new(token.clone())) -} diff --git a/language/move-bytecode-verifier/src/regression_tests/reference_analysis.rs b/language/move-bytecode-verifier/src/regression_tests/reference_analysis.rs index afaf20fac6..e901a9f04a 100644 --- a/language/move-bytecode-verifier/src/regression_tests/reference_analysis.rs +++ b/language/move-bytecode-verifier/src/regression_tests/reference_analysis.rs @@ -14,7 +14,7 @@ use move_binary_format::{ use move_core_types::{ account_address::AccountAddress, identifier::Identifier, vm_status::StatusCode, }; -use std::str::FromStr; +use core::str::FromStr; #[test] fn unbalanced_stack_crash() { diff --git a/language/move-core/types/src/u256.rs b/language/move-core/types/src/u256.rs index b6de1eefcb..73ba6eb2e8 100644 --- a/language/move-core/types/src/u256.rs +++ b/language/move-core/types/src/u256.rs @@ -419,7 +419,7 @@ impl U256 { Self(self.0.overflowing_mul(rhs.0).0) } - /// Implementation of widenining multiply + /*/// Implementation of widenining multiply /// https://github.com/rust-random/rand/blob/master/src/distributions/utils.rs #[inline(always)] fn wmul(self, b: Self) -> (Self, Self) { @@ -441,7 +441,7 @@ impl U256 { high += (self >> half).wrapping_mul(b >> half); (high, low) - } + }*/ } impl From for U256 {