Skip to content

Commit

Permalink
fix(runtime): Fix empty method_names bug (#2188)
Browse files Browse the repository at this point in the history
Fixes: #2183

# Test plan:
- Extracted the code into utils crate and added unit tests.
  • Loading branch information
Evgeny Kuzyakov authored Feb 25, 2020
1 parent d4a07fa commit 29cb252
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 52 deletions.
50 changes: 25 additions & 25 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion runtime/near-runtime-fees/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "near-runtime-fees"
version = "0.4.4"
version = "0.4.5"
authors = ["Near Inc <[email protected]>"]
edition = "2018"
license = "Apache-2.0"
Expand Down
2 changes: 1 addition & 1 deletion runtime/near-vm-errors/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "near-vm-errors"
version = "0.4.4"
version = "0.4.5"
authors = ["Near Inc <[email protected]>"]
edition = "2018"
license = "Apache-2.0"
Expand Down
6 changes: 3 additions & 3 deletions runtime/near-vm-logic/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "near-vm-logic"
version = "0.4.4"
version = "0.4.5"
authors = ["Near Inc <[email protected]>"]
edition = "2018"
license = "Apache-2.0"
Expand All @@ -16,8 +16,8 @@ This crate implements the specification of the interface that Near blockchain ex
byteorder = "1.2"
bs58 = "0.3"
serde = { version = "1.0", features = ["derive"] }
near-runtime-fees = { path = "../near-runtime-fees", version = "0.4.4" }
near-vm-errors = { path = "../near-vm-errors", version = "0.4.4" }
near-runtime-fees = { path = "../near-runtime-fees", version = "0.4.5" }
near-vm-errors = { path = "../near-vm-errors", version = "0.4.5" }

[dev-dependencies]
serde_json = {version= "1.0", features= ["preserve_order"]}
Expand Down
3 changes: 2 additions & 1 deletion runtime/near-vm-logic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ mod logic;
#[cfg(not(target_arch = "wasm32"))]
pub mod mocks;
pub mod serde_with;

pub mod types;
mod utils;

pub use config::{ExtCosts, ExtCostsConfig, VMConfig, VMLimitConfig};
pub use context::VMContext;
pub use dependencies::{External, MemoryLike, ValuePtr};
Expand Down
16 changes: 3 additions & 13 deletions runtime/near-vm-logic/src/logic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::types::{
AccountId, Balance, Gas, IteratorIndex, PromiseIndex, PromiseResult, ReceiptIndex, ReturnData,
StorageUsage,
};
use crate::utils::split_method_names;
use crate::{ExtCosts, HostError, VMLogicError, ValuePtr};
use byteorder::ByteOrder;
use near_runtime_fees::RuntimeFeesConfig;
Expand Down Expand Up @@ -1436,20 +1437,9 @@ impl<'a> VMLogic<'a> {
let allowance = self.memory_get_u128(allowance_ptr)?;
let allowance = if allowance > 0 { Some(allowance) } else { None };
let receiver_id = self.read_and_parse_account_id(receiver_id_ptr, receiver_id_len)?;
let method_names =
let raw_method_names =
self.get_vec_from_memory_or_register(method_names_ptr, method_names_len)?;
// Use `,` separator to split `method_names` into a vector of method names.
let method_names =
method_names
.split(|c| *c == b',')
.map(|v| {
if v.is_empty() {
Err(HostError::EmptyMethodName.into())
} else {
Ok(v.to_vec())
}
})
.collect::<Result<Vec<_>>>()?;
let method_names = split_method_names(&raw_method_names)?;

let (receipt_idx, sir) = self.promise_idx_to_receipt_idx_with_sir(promise_idx)?;

Expand Down
80 changes: 80 additions & 0 deletions runtime/near-vm-logic/src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use near_vm_errors::{HostError, VMLogicError};

type Result<T> = ::std::result::Result<T, VMLogicError>;

/// Uses `,` separator to split `method_names` into a vector of method names.
/// Returns an empty vec if the empty slice is given.
/// Throws `HostError::EmptyMethodName` in case there is an empty method name inside.
pub(crate) fn split_method_names(method_names: &[u8]) -> Result<Vec<Vec<u8>>> {
if method_names.is_empty() {
Ok(vec![])
} else {
method_names
.split(|c| *c == b',')
.map(
|v| {
if v.is_empty() {
Err(HostError::EmptyMethodName.into())
} else {
Ok(v.to_vec())
}
},
)
.collect::<Result<Vec<_>>>()
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_split_method_names_empty() {
assert_eq!(split_method_names(b""), Ok(vec![]));
}

#[test]
fn test_split_method_one_name() {
assert_eq!(split_method_names(b"hello"), Ok(vec![b"hello".to_vec()]));
}

#[test]
fn test_split_method_two_method_names() {
assert_eq!(
split_method_names(b"hello,world"),
Ok(vec![b"hello".to_vec(), b"world".to_vec()])
);
}

#[test]
fn test_split_empty_method_name_inside() {
assert_eq!(
split_method_names(b"hello,,world"),
Err(VMLogicError::HostError(HostError::EmptyMethodName))
);
}

#[test]
fn test_split_empty_method_name_front() {
assert_eq!(
split_method_names(b",world"),
Err(VMLogicError::HostError(HostError::EmptyMethodName))
);
}

#[test]
fn test_split_empty_method_name_back() {
assert_eq!(
split_method_names(b"world,"),
Err(VMLogicError::HostError(HostError::EmptyMethodName))
);
}

#[test]
fn test_split_empty_method_name_comma_only() {
assert_eq!(
split_method_names(b","),
Err(VMLogicError::HostError(HostError::EmptyMethodName))
);
}
}
8 changes: 4 additions & 4 deletions runtime/near-vm-runner-standalone/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "near-vm-runner-standalone"
version = "0.4.4"
version = "0.4.5"
authors = ["Near Inc <[email protected]>"]
edition = "2018"
license = "Apache-2.0"
Expand All @@ -21,6 +21,6 @@ to make sure it has expected behavior once deployed to the blockchain.
[dependencies]
serde_json = "1.0"
clap = "2.33.0"
near-vm-logic = { path = "../near-vm-logic", version = "0.4.4"}
near-vm-runner = { path = "../near-vm-runner", version = "0.4.4" }
near-runtime-fees = { path = "../near-runtime-fees", version = "0.4.4" }
near-vm-logic = { path = "../near-vm-logic", version = "0.4.5"}
near-vm-runner = { path = "../near-vm-runner", version = "0.4.5" }
near-runtime-fees = { path = "../near-runtime-fees", version = "0.4.5" }
8 changes: 4 additions & 4 deletions runtime/near-vm-runner/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "near-vm-runner"
version = "0.4.4"
version = "0.4.5"
authors = ["Near Inc <[email protected]>"]
edition = "2018"
license = "Apache-2.0"
Expand All @@ -16,9 +16,9 @@ This crate implements the specification of the interface that Near blockchain ex
cached = "0.11.0"
wasmer-runtime = { version = "0.13.1", features = ["default-backend-singlepass"], default-features = false }
wasmer-runtime-core = { version = "0.13.1" }
near-runtime-fees = { path="../near-runtime-fees", version = "0.4.4" }
near-vm-logic = { path="../near-vm-logic", version = "0.4.4", default-features = false, features = []}
near-vm-errors = { path = "../near-vm-errors", version = "0.4.4" }
near-runtime-fees = { path="../near-runtime-fees", version = "0.4.5" }
near-vm-logic = { path="../near-vm-logic", version = "0.4.5", default-features = false, features = []}
near-vm-errors = { path = "../near-vm-errors", version = "0.4.5" }
pwasm-utils = "0.12.0"
parity-wasm = "0.41.0"
wasmparser = "0.44"
Expand Down

0 comments on commit 29cb252

Please sign in to comment.