From df9beb5a400e74adef9943a63df67e3080153a00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Losiggio?= Date: Thu, 23 Nov 2023 14:06:04 -0300 Subject: [PATCH 1/6] Insufficiently random values detector and test cases. --- .../insufficiently-random-values/Cargo.toml | 24 ++++++++ .../insufficiently-random-values/src/lib.rs | 45 ++++++++++++++ scout-audit-internal/src/detector.rs | 2 + .../src/detector/lint_message.rs | 1 + .../remediated-example/Cargo.toml | 31 ++++++++++ .../remediated-example/src/lib.rs | 28 +++++++++ .../remediated-example/src/test.rs | 24 ++++++++ .../vulnerable-example/Cargo.toml | 36 +++++++++++ .../vulnerable-example/src/lib.rs | 36 +++++++++++ .../vulnerable-example/src/test.rs | 59 +++++++++++++++++++ 10 files changed, 286 insertions(+) create mode 100644 detectors/insufficiently-random-values/Cargo.toml create mode 100644 detectors/insufficiently-random-values/src/lib.rs create mode 100644 test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/Cargo.toml create mode 100644 test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/src/lib.rs create mode 100644 test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/src/test.rs create mode 100644 test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/Cargo.toml create mode 100644 test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/src/lib.rs create mode 100644 test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/src/test.rs diff --git a/detectors/insufficiently-random-values/Cargo.toml b/detectors/insufficiently-random-values/Cargo.toml new file mode 100644 index 00000000..65b01ed0 --- /dev/null +++ b/detectors/insufficiently-random-values/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "insufficiently-random-values" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +clippy_utils = { git = "https://github.com/rust-lang/rust-clippy", rev = "7671c283a50b5d1168841f3014b14000f01dd204" } +dylint_linting = { workspace = true } +if_chain = { workspace = true } +semver = "1.0.4" +serde_json = "1.0" +toml = "0.7.6" +ureq = { version = "2.7.1", features = ["json"] } + +scout-audit-internal = { workspace = true } + +[dev-dependencies] +dylint_testing = { workspace = true } + +[package.metadata.rust-analyzer] +rustc_private = true diff --git a/detectors/insufficiently-random-values/src/lib.rs b/detectors/insufficiently-random-values/src/lib.rs new file mode 100644 index 00000000..5841f123 --- /dev/null +++ b/detectors/insufficiently-random-values/src/lib.rs @@ -0,0 +1,45 @@ +#![feature(rustc_private)] + +extern crate rustc_hir; + +use if_chain::if_chain; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use scout_audit_internal::Detector; + +dylint_linting::declare_late_lint! { + /// ### What it does + /// This detector prevents the usage of timestamp/sequence number and modulo operator as a random number source. + /// + /// ### Why is this bad? + /// The value of the block timestamp and block sequence can be manipulated by validators, which means they're not a secure source of randomness. Therefore, they shouldn't be used for generating random numbers, especially in the context of a betting contract where the outcomes of bets could be manipulated. + /// + /// ### Example + /// ```rust + /// let pseudo_random = env.ledger().timestamp() % max_val; + /// ``` + /// + pub INSUFFICIENTLY_RANDOM_VALUES, + Warn, + Detector::InsufficientlyRandomValues.get_lint_message() +} + +impl<'tcx> LateLintPass<'tcx> for InsufficientlyRandomValues { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + if_chain! { + if let ExprKind::Binary(op, lexp, _rexp) = expr.kind; + if op.node == BinOpKind::Rem; + if let ExprKind::MethodCall(path, _, _, _) = lexp.kind; + if path.ident.as_str() == "timestamp" || + path.ident.as_str() == "sequence"; + then { + Detector::InsufficientlyRandomValues.span_lint_and_help( + cx, + INSUFFICIENTLY_RANDOM_VALUES, + expr.span, + &format!("This expression seems to use ledger().{}() as a pseudo random number",path.ident.as_str()), + ); + } + } + } +} diff --git a/scout-audit-internal/src/detector.rs b/scout-audit-internal/src/detector.rs index 1df8403d..96e9c100 100644 --- a/scout-audit-internal/src/detector.rs +++ b/scout-audit-internal/src/detector.rs @@ -30,6 +30,7 @@ use strum::{Display, EnumIter}; #[strum(serialize_all = "kebab-case")] pub enum Detector { OverflowCheck, + InsufficientlyRandomValues, } impl Detector { @@ -37,6 +38,7 @@ impl Detector { pub const fn get_lint_message(&self) -> &'static str { match self { Detector::OverflowCheck => OVERFLOW_CHECK, + Detector::InsufficientlyRandomValues => INSUFFICIENTLY_RANDOM_VALUES, } } diff --git a/scout-audit-internal/src/detector/lint_message.rs b/scout-audit-internal/src/detector/lint_message.rs index 7c9afbbb..a82e0b1c 100644 --- a/scout-audit-internal/src/detector/lint_message.rs +++ b/scout-audit-internal/src/detector/lint_message.rs @@ -1 +1,2 @@ pub const OVERFLOW_CHECK: &str = "Use overflow-checks = true in cargo.toml profile"; +pub const INSUFFICIENTLY_RANDOM_VALUES: &str = "Use env.prng() to generate random numbers, and remember that all random numbers are under the control of validators"; diff --git a/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/Cargo.toml b/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/Cargo.toml new file mode 100644 index 00000000..eb77cb17 --- /dev/null +++ b/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/Cargo.toml @@ -0,0 +1,31 @@ + +[package] +name = "insufficiently-random-values" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +soroban-sdk = "20.0.0-rc2" + +[dev_dependencies] +soroban-sdk = { version = "20.0.0-rc2", features = ["testutils"] } + +[features] +testutils = ["soroban-sdk/testutils"] + +[profile.release] +opt-level = "z" +overflow-checks = true +debug = 0 +strip = "symbols" +debug-assertions = false +panic = "abort" +codegen-units = 1 +lto = true + +[profile.release-with-logs] +inherits = "release" +debug-assertions = true \ No newline at end of file diff --git a/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/src/lib.rs b/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/src/lib.rs new file mode 100644 index 00000000..145e43bd --- /dev/null +++ b/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/src/lib.rs @@ -0,0 +1,28 @@ +#![no_std] + +use soroban_sdk::{contract, contracterror, contractimpl, symbol_short, vec, Env, Symbol, Vec}; + +#[contracterror] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[repr(u32)] +pub enum Error { + MaxValZero = 1, +} + +#[contract] +pub struct Contract; + +#[contractimpl] +impl Contract { + pub fn generate_random_value(env: Env, max_val: u64) -> Result { + if max_val == 0 { + Err(Error::MaxValZero) + } else { + let val = env.prng().u64_in_range(0..max_val); + Ok(val) + } + } +} + +#[cfg(test)] +mod test; diff --git a/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/src/test.rs b/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/src/test.rs new file mode 100644 index 00000000..35f42f89 --- /dev/null +++ b/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/src/test.rs @@ -0,0 +1,24 @@ +extern crate std; + +use std::dbg; + +use soroban_sdk::{ + symbol_short, + testutils::{Ledger, LedgerInfo}, + vec, Bytes, Env, +}; + +use crate::{Contract, ContractClient}; + +#[test] +fn random_value_sequence() { + let env = Env::default(); + let contract_id = env.register_contract(None, Contract); + let client = ContractClient::new(&env, &contract_id); + + assert_eq!(client.generate_random_value(&10), 6); + assert_eq!(client.generate_random_value(&10), 5); + assert_eq!(client.generate_random_value(&10), 8); + assert_eq!(client.generate_random_value(&10), 8); + assert_eq!(client.generate_random_value(&10), 4); +} diff --git a/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/Cargo.toml b/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/Cargo.toml new file mode 100644 index 00000000..b8fa154a --- /dev/null +++ b/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/Cargo.toml @@ -0,0 +1,36 @@ + +[package] +name = "insufficiently-random-values" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +soroban-sdk = "20.0.0-rc2" + +[dev_dependencies] +soroban-sdk = { version = "20.0.0-rc2", features = ["testutils"] } + +[features] +testutils = ["soroban-sdk/testutils"] + +[profile.release] +opt-level = "z" +overflow-checks = true +debug = 0 +strip = "symbols" +debug-assertions = false +panic = "abort" +codegen-units = 1 +lto = true + +[profile.release-with-logs] +inherits = "release" +debug-assertions = true + +[workspace.metadata.dylint] +libraries = [ + { path = "/home/tiki/trabajo/scout-soroban/detectors/insufficiently-random-values" }, +] \ No newline at end of file diff --git a/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/src/lib.rs b/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/src/lib.rs new file mode 100644 index 00000000..43a7f10d --- /dev/null +++ b/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/src/lib.rs @@ -0,0 +1,36 @@ +#![no_std] + +use soroban_sdk::{contract, contracterror, contractimpl, Env}; + +#[contracterror] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[repr(u32)] +pub enum Error { + MaxValZero = 1, +} + +#[contract] +pub struct Contract; + +#[contractimpl] +impl Contract { + pub fn generate_random_value_timestamp(env: Env, max_val: u64) -> Result { + if max_val == 0 { + Err(Error::MaxValZero) + } else { + let val = env.ledger().timestamp() % max_val; + Ok(val) + } + } + pub fn generate_random_value_sequence(env: Env, max_val: u32) -> Result { + if max_val == 0 { + Err(Error::MaxValZero) + } else { + let val = env.ledger().sequence() % max_val; + Ok(val) + } + } +} + +#[cfg(test)] +mod test; diff --git a/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/src/test.rs b/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/src/test.rs new file mode 100644 index 00000000..2a8ba556 --- /dev/null +++ b/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/src/test.rs @@ -0,0 +1,59 @@ +extern crate std; + +use soroban_sdk::{ + testutils::{Ledger, LedgerInfo}, + Env, +}; + +use crate::{Contract, ContractClient}; + +#[test] +fn random_value_sequence() { + let env = Env::default(); + let contract_id = env.register_contract(None, Contract); + let client = ContractClient::new(&env, &contract_id); + + let mut ledger = LedgerInfo::default(); + ledger.sequence_number = 0; + env.ledger().set(ledger.clone()); + + let mut random = client.generate_random_value_sequence(&10); + assert_eq!(random, 0); + + ledger.sequence_number = 1; + env.ledger().set(ledger.clone()); + + random = client.generate_random_value_sequence(&10); + assert_eq!(random, 1); + + ledger.sequence_number = 11; + env.ledger().set(ledger.clone()); + + random = client.generate_random_value_sequence(&10); + assert_eq!(random, 1); +} +#[test] +fn random_value_timestamp() { + let env = Env::default(); + let contract_id = env.register_contract(None, Contract); + let client = ContractClient::new(&env, &contract_id); + + let mut ledger = LedgerInfo::default(); + ledger.timestamp = 0; + env.ledger().set(ledger.clone()); + + let mut random = client.generate_random_value_timestamp(&10); + assert_eq!(random, 0); + + ledger.timestamp = 1; + env.ledger().set(ledger.clone()); + + random = client.generate_random_value_timestamp(&10); + assert_eq!(random, 1); + + ledger.timestamp = 11; + env.ledger().set(ledger.clone()); + + random = client.generate_random_value_timestamp(&10); + assert_eq!(random, 1); +} From 921d8bc5f2f46b1e03edb19f5847d64b7c40e551 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Losiggio?= Date: Fri, 1 Dec 2023 01:59:47 -0300 Subject: [PATCH 2/6] detector added to ci --- .github/workflows/test-detectors.yml | 1 + scout-audit-internal/src/detector.rs | 6 +++--- scout-audit-internal/src/detector/lint_message.rs | 3 +-- .../remediated-example/Cargo.toml | 2 +- .../vulnerable-example/Cargo.toml | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test-detectors.yml b/.github/workflows/test-detectors.yml index ed9cf030..e160ad5c 100644 --- a/.github/workflows/test-detectors.yml +++ b/.github/workflows/test-detectors.yml @@ -97,6 +97,7 @@ jobs: - macos-latest test: [ + "insufficiently-random-values", "divide-before-multiply", "overflow-check", "unsafe-expect", diff --git a/scout-audit-internal/src/detector.rs b/scout-audit-internal/src/detector.rs index 6c80774d..e8394dcc 100644 --- a/scout-audit-internal/src/detector.rs +++ b/scout-audit-internal/src/detector.rs @@ -27,8 +27,8 @@ use strum::{Display, EnumIter}; #[strum(serialize_all = "kebab-case")] pub enum Detector { DivideBeforeMultiply, - OverflowCheck, InsufficientlyRandomValues, + OverflowCheck, UnsafeExpect, UnsafeUnwrap, } @@ -37,8 +37,8 @@ impl Detector { /// Returns the lint message for the detector. pub const fn get_lint_message(&self) -> &'static str { match self { - Detector::OverflowCheck => OVERFLOW_CHECK, - Detector::InsufficientlyRandomValues => INSUFFICIENTLY_RANDOM_VALUES, + Detector::OverflowCheck => OVERFLOW_CHECK_LINT_MESSAGE, + Detector::InsufficientlyRandomValues => INSUFFICIENTLY_RANDOM_VALUES_LINT_MESSAGE, Detector::DivideBeforeMultiply => DIVIDE_BEFORE_MULTIPLY_LINT_MESSAGE, Detector::UnsafeExpect => UNSAFE_EXPECT_LINT_MESSAGE, Detector::UnsafeUnwrap => UNSAFE_UNWRAP_MESSAGE, diff --git a/scout-audit-internal/src/detector/lint_message.rs b/scout-audit-internal/src/detector/lint_message.rs index b879edcf..47cac674 100644 --- a/scout-audit-internal/src/detector/lint_message.rs +++ b/scout-audit-internal/src/detector/lint_message.rs @@ -1,5 +1,4 @@ -pub const OVERFLOW_CHECK: &str = "Use overflow-checks = true in cargo.toml profile"; -pub const INSUFFICIENTLY_RANDOM_VALUES: &str = "Use env.prng() to generate random numbers, and remember that all random numbers are under the control of validators"; +pub const INSUFFICIENTLY_RANDOM_VALUES_LINT_MESSAGE: &str = "Use env.prng() to generate random numbers, and remember that all random numbers are under the control of validators"; pub const DIVIDE_BEFORE_MULTIPLY_LINT_MESSAGE: &str = "Division before multiplication might result in a loss of precision"; pub const OVERFLOW_CHECK_LINT_MESSAGE: &str = "Use `overflow-checks = true` in Cargo.toml profile"; diff --git a/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/Cargo.toml b/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/Cargo.toml index eb77cb17..a0a63b5d 100644 --- a/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/Cargo.toml +++ b/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "insufficiently-random-values" +name = "insufficiently-random-values-remediated-1" version = "0.1.0" edition = "2021" diff --git a/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/Cargo.toml b/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/Cargo.toml index b8fa154a..8df3f890 100644 --- a/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/Cargo.toml +++ b/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "insufficiently-random-values" +name = "insufficiently-random-values-vulnerable-1" version = "0.1.0" edition = "2021" From 08dc819124175282b1855c5624d357df413ccf26 Mon Sep 17 00:00:00 2001 From: Jose Garcia Crosta Date: Fri, 1 Dec 2023 11:39:38 -0300 Subject: [PATCH 3/6] Revise detector dependencies --- detectors/insufficiently-random-values/Cargo.toml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/detectors/insufficiently-random-values/Cargo.toml b/detectors/insufficiently-random-values/Cargo.toml index 65b01ed0..e6fc20e3 100644 --- a/detectors/insufficiently-random-values/Cargo.toml +++ b/detectors/insufficiently-random-values/Cargo.toml @@ -7,13 +7,9 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -clippy_utils = { git = "https://github.com/rust-lang/rust-clippy", rev = "7671c283a50b5d1168841f3014b14000f01dd204" } +clippy_utils = { workspace = true } dylint_linting = { workspace = true } if_chain = { workspace = true } -semver = "1.0.4" -serde_json = "1.0" -toml = "0.7.6" -ureq = { version = "2.7.1", features = ["json"] } scout-audit-internal = { workspace = true } From 2be0e2332e13cc743efb2b4423b958f52d74310a Mon Sep 17 00:00:00 2001 From: Jose Garcia Crosta Date: Fri, 1 Dec 2023 11:39:56 -0300 Subject: [PATCH 4/6] Remove dylint reference --- .../vulnerable-example/Cargo.toml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/Cargo.toml b/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/Cargo.toml index 8df3f890..8d0e40bb 100644 --- a/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/Cargo.toml +++ b/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/Cargo.toml @@ -29,8 +29,3 @@ lto = true [profile.release-with-logs] inherits = "release" debug-assertions = true - -[workspace.metadata.dylint] -libraries = [ - { path = "/home/tiki/trabajo/scout-soroban/detectors/insufficiently-random-values" }, -] \ No newline at end of file From ffbf75f698e8c5d0a27db21ec718f14e1238407f Mon Sep 17 00:00:00 2001 From: Jose Garcia Crosta Date: Fri, 1 Dec 2023 11:49:46 -0300 Subject: [PATCH 5/6] Clean remediated test-case imports and move tests --- .../remediated-example/Cargo.toml | 2 +- .../remediated-example/src/lib.rs | 30 +++++++++++++++++-- .../remediated-example/src/test.rs | 24 --------------- 3 files changed, 29 insertions(+), 27 deletions(-) delete mode 100644 test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/src/test.rs diff --git a/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/Cargo.toml b/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/Cargo.toml index a0a63b5d..99e57ca8 100644 --- a/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/Cargo.toml +++ b/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/Cargo.toml @@ -28,4 +28,4 @@ lto = true [profile.release-with-logs] inherits = "release" -debug-assertions = true \ No newline at end of file +debug-assertions = true diff --git a/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/src/lib.rs b/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/src/lib.rs index 145e43bd..a05d3ed3 100644 --- a/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/src/lib.rs +++ b/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/src/lib.rs @@ -1,6 +1,6 @@ #![no_std] -use soroban_sdk::{contract, contracterror, contractimpl, symbol_short, vec, Env, Symbol, Vec}; +use soroban_sdk::{contract, contracterror, contractimpl, Env}; #[contracterror] #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] @@ -25,4 +25,30 @@ impl Contract { } #[cfg(test)] -mod test; +mod test { + use soroban_sdk::Env; + + use crate::{Contract, ContractClient}; + + #[test] + fn random_value_sequence() { + // Given + let env = Env::default(); + let contract_id = env.register_contract(None, Contract); + let client = ContractClient::new(&env, &contract_id); + + // When + let first_random_value = client.generate_random_value(&10); + let second_random_value = client.generate_random_value(&10); + let third_random_value = client.generate_random_value(&10); + let fourth_random_value = client.generate_random_value(&10); + let fifth_random_value = client.generate_random_value(&10); + + // Then + assert_eq!(first_random_value, 6); + assert_eq!(second_random_value, 5); + assert_eq!(third_random_value, 8); + assert_eq!(fourth_random_value, 8); + assert_eq!(fifth_random_value, 4); + } +} diff --git a/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/src/test.rs b/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/src/test.rs deleted file mode 100644 index 35f42f89..00000000 --- a/test-cases/insufficiently-random-values/insufficiently-random-values-1/remediated-example/src/test.rs +++ /dev/null @@ -1,24 +0,0 @@ -extern crate std; - -use std::dbg; - -use soroban_sdk::{ - symbol_short, - testutils::{Ledger, LedgerInfo}, - vec, Bytes, Env, -}; - -use crate::{Contract, ContractClient}; - -#[test] -fn random_value_sequence() { - let env = Env::default(); - let contract_id = env.register_contract(None, Contract); - let client = ContractClient::new(&env, &contract_id); - - assert_eq!(client.generate_random_value(&10), 6); - assert_eq!(client.generate_random_value(&10), 5); - assert_eq!(client.generate_random_value(&10), 8); - assert_eq!(client.generate_random_value(&10), 8); - assert_eq!(client.generate_random_value(&10), 4); -} From c5908241878893adaff2519c15127fcd0a9eb722 Mon Sep 17 00:00:00 2001 From: Jose Garcia Crosta Date: Fri, 1 Dec 2023 11:59:22 -0300 Subject: [PATCH 6/6] Move vulnerable tests --- .../vulnerable-example/src/lib.rs | 67 ++++++++++++++++++- .../vulnerable-example/src/test.rs | 59 ---------------- 2 files changed, 66 insertions(+), 60 deletions(-) delete mode 100644 test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/src/test.rs diff --git a/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/src/lib.rs b/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/src/lib.rs index 43a7f10d..d5bbeedf 100644 --- a/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/src/lib.rs +++ b/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/src/lib.rs @@ -33,4 +33,69 @@ impl Contract { } #[cfg(test)] -mod test; +mod test { + use soroban_sdk::{ + testutils::{Ledger, LedgerInfo}, + Env, + }; + + use crate::{Contract, ContractClient}; + + #[test] + fn random_value_sequence() { + // Given + let env = Env::default(); + let contract_id = env.register_contract(None, Contract); + let client = ContractClient::new(&env, &contract_id); + + // When + let mut ledger = LedgerInfo { + sequence_number: 0, + ..Default::default() + }; + env.ledger().set(ledger.clone()); + let first_random_value = client.generate_random_value_sequence(&10); + + ledger.sequence_number = 1; + env.ledger().set(ledger.clone()); + let second_random_value = client.generate_random_value_sequence(&10); + + ledger.sequence_number = 11; + env.ledger().set(ledger.clone()); + let third_random_value = client.generate_random_value_sequence(&10); + + // Then + assert_eq!(first_random_value, 0); + assert_eq!(second_random_value, 1); + assert_eq!(third_random_value, 1); + } + + #[test] + fn random_value_timestamp() { + // Given + let env = Env::default(); + let contract_id = env.register_contract(None, Contract); + let client = ContractClient::new(&env, &contract_id); + + // When + let mut ledger = LedgerInfo { + timestamp: 0, + ..Default::default() + }; + env.ledger().set(ledger.clone()); + let first_random_value = client.generate_random_value_timestamp(&10); + + ledger.timestamp = 1; + env.ledger().set(ledger.clone()); + let second_random_value = client.generate_random_value_timestamp(&10); + + ledger.timestamp = 11; + env.ledger().set(ledger.clone()); + let third_random_value = client.generate_random_value_timestamp(&10); + + // Then + assert_eq!(first_random_value, 0); + assert_eq!(second_random_value, 1); + assert_eq!(third_random_value, 1); + } +} diff --git a/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/src/test.rs b/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/src/test.rs deleted file mode 100644 index 2a8ba556..00000000 --- a/test-cases/insufficiently-random-values/insufficiently-random-values-1/vulnerable-example/src/test.rs +++ /dev/null @@ -1,59 +0,0 @@ -extern crate std; - -use soroban_sdk::{ - testutils::{Ledger, LedgerInfo}, - Env, -}; - -use crate::{Contract, ContractClient}; - -#[test] -fn random_value_sequence() { - let env = Env::default(); - let contract_id = env.register_contract(None, Contract); - let client = ContractClient::new(&env, &contract_id); - - let mut ledger = LedgerInfo::default(); - ledger.sequence_number = 0; - env.ledger().set(ledger.clone()); - - let mut random = client.generate_random_value_sequence(&10); - assert_eq!(random, 0); - - ledger.sequence_number = 1; - env.ledger().set(ledger.clone()); - - random = client.generate_random_value_sequence(&10); - assert_eq!(random, 1); - - ledger.sequence_number = 11; - env.ledger().set(ledger.clone()); - - random = client.generate_random_value_sequence(&10); - assert_eq!(random, 1); -} -#[test] -fn random_value_timestamp() { - let env = Env::default(); - let contract_id = env.register_contract(None, Contract); - let client = ContractClient::new(&env, &contract_id); - - let mut ledger = LedgerInfo::default(); - ledger.timestamp = 0; - env.ledger().set(ledger.clone()); - - let mut random = client.generate_random_value_timestamp(&10); - assert_eq!(random, 0); - - ledger.timestamp = 1; - env.ledger().set(ledger.clone()); - - random = client.generate_random_value_timestamp(&10); - assert_eq!(random, 1); - - ledger.timestamp = 11; - env.ledger().set(ledger.clone()); - - random = client.generate_random_value_timestamp(&10); - assert_eq!(random, 1); -}