diff --git a/.github/workflows/general-rust.yml b/.github/workflows/general-rust.yml index 824bbc8c..d8de7de7 100644 --- a/.github/workflows/general-rust.yml +++ b/.github/workflows/general-rust.yml @@ -6,9 +6,8 @@ on: - "detectors/**" - "test-cases/**" - "scripts/**" - paths-ignore: - - "detectors/**/*.md" - - "test-cases/**/*.md" + - "!detectors/**/*.md" + - "!test-cases/**/*.md" env: CARGO_TERM_COLOR: always diff --git a/.github/workflows/test-detectors.yml b/.github/workflows/test-detectors.yml index 79946298..ea1e7ded 100644 --- a/.github/workflows/test-detectors.yml +++ b/.github/workflows/test-detectors.yml @@ -6,9 +6,8 @@ on: - "detectors/**" - "test-cases/**" - "scripts/**" - paths-ignore: - - "detectors/**/*.md" - - "test-cases/**/*.md" + - "!detectors/**/*.md" + - "!test-cases/**/*.md" env: CARGO_TERM_COLOR: always diff --git a/detectors/unsafe-expect/src/lib.rs b/detectors/unsafe-expect/src/lib.rs index 9afeb1ed..e331b61a 100644 --- a/detectors/unsafe-expect/src/lib.rs +++ b/detectors/unsafe-expect/src/lib.rs @@ -1,18 +1,25 @@ #![feature(rustc_private)] +#![allow(clippy::enum_variant_names)] extern crate rustc_hir; extern crate rustc_span; +use std::{collections::HashSet, hash::Hash}; + +use if_chain::if_chain; +use rustc_hir::BinOpKind; use rustc_hir::{ + def::Res, def_id::LocalDefId, intravisit::{walk_expr, FnKind, Visitor}, - Body, Expr, ExprKind, FnDecl, + Body, Expr, ExprKind, FnDecl, HirId, Local, QPath, UnOp, }; use rustc_lint::{LateContext, LateLintPass}; -use rustc_span::{Span, Symbol}; -use scout_audit_clippy_utils::diagnostics::span_lint_and_help; +use rustc_span::{sym, Span, Symbol}; +use scout_audit_clippy_utils::{diagnostics::span_lint_and_help, higher}; const LINT_MESSAGE: &str = "Unsafe usage of `expect`"; +const PANIC_INDUCING_FUNCTIONS: [&str; 2] = ["panic", "bail"]; dylint_linting::declare_late_lint! { /// ### What it does @@ -57,53 +64,263 @@ dylint_linting::declare_late_lint! { } } -impl<'tcx> LateLintPass<'tcx> for UnsafeExpect { - fn check_fn( - &mut self, - cx: &LateContext<'tcx>, - _: FnKind<'tcx>, - _: &'tcx FnDecl<'tcx>, - body: &'tcx Body<'tcx>, - _: Span, - _: LocalDefId, - ) { - struct UnsafeExpectVisitor { - has_expect: bool, - has_expect_span: Vec>, +/// Represents the type of check performed on method call expressions to determine their safety or behavior. +#[derive(Clone, Copy, Hash, Eq, PartialEq)] +enum CheckType { + IsSome, + IsNone, + IsOk, + IsErr, +} + +impl CheckType { + fn from_method_name(name: Symbol) -> Option { + match name.as_str() { + "is_some" => Some(Self::IsSome), + "is_none" => Some(Self::IsNone), + "is_ok" => Some(Self::IsOk), + "is_err" => Some(Self::IsErr), + _ => None, + } + } + + fn inverse(self) -> Self { + match self { + Self::IsSome => Self::IsNone, + Self::IsNone => Self::IsSome, + Self::IsOk => Self::IsErr, + Self::IsErr => Self::IsOk, + } + } + + /// Determines if the check type implies execution should halt, such as in error conditions. + fn should_halt_execution(self) -> bool { + matches!(self, Self::IsNone | Self::IsErr) + } + + /// Determines if it is safe to expect the value without further checks, i.e., the value is present. + fn is_safe_to_expect(self) -> bool { + matches!(self, Self::IsSome | Self::IsOk) + } +} + +/// Represents a conditional checker that is used to analyze `if` or `if let` expressions. +#[derive(Clone, Copy, Hash, Eq, PartialEq)] +struct ConditionalChecker { + check_type: CheckType, + checked_expr_hir_id: HirId, +} + +impl ConditionalChecker { + /// Handle te condition of the `if` or `if let` expression. + fn handle_condition(condition: &Expr<'_>, inverse: bool) -> HashSet { + if_chain! { + if let ExprKind::MethodCall(path_segment, receiver, _, _) = condition.kind; + if let Some(check_type) = CheckType::from_method_name(path_segment.ident.name); + if let ExprKind::Path(QPath::Resolved(_, checked_expr_path)) = receiver.kind; + if let Res::Local(checked_expr_hir_id) = checked_expr_path.res; + then { + let check_type = if inverse { check_type.inverse() } else { check_type }; + return std::iter::once(Self { check_type, checked_expr_hir_id }).collect(); + } + } + HashSet::new() + } + + /// Constructs a ConditionalChecker from an expression if it matches a method call with a valid CheckType. + fn from_expression(condition: &Expr<'_>) -> HashSet { + match condition.kind { + // Single `not` expressions are supported + ExprKind::Unary(op, condition) => Self::handle_condition(condition, op == UnOp::Not), + // Multiple `or` expressions are supported + ExprKind::Binary(op, left_condition, right_condition) if op.node == BinOpKind::Or => { + let mut result = Self::from_expression(left_condition); + result.extend(Self::from_expression(right_condition)); + result + } + ExprKind::MethodCall(..) => Self::handle_condition(condition, false), + _ => HashSet::new(), + } + } +} + +/// Main unsafe-expect visitor +struct UnsafeExpectVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + conditional_checker: HashSet, + checked_exprs: HashSet, +} + +impl UnsafeExpectVisitor<'_, '_> { + fn is_panic_inducing_call(&self, func: &Expr<'_>) -> bool { + if let ExprKind::Path(QPath::Resolved(_, path)) = &func.kind { + return PANIC_INDUCING_FUNCTIONS.iter().any(|&func| { + path.segments + .iter() + .any(|segment| segment.ident.name.as_str().contains(func)) + }); + } + false + } + + fn get_expect_info(&self, receiver: &Expr<'_>) -> Option { + if_chain! { + if let ExprKind::Path(QPath::Resolved(_, path)) = &receiver.kind; + if let Res::Local(hir_id) = path.res; + then { + return Some(hir_id); + } + } + None + } + + fn set_conditional_checker(&mut self, conditional_checkers: &HashSet) { + for checker in conditional_checkers { + self.conditional_checker.insert(*checker); + if checker.check_type.is_safe_to_expect() { + self.checked_exprs.insert(checker.checked_expr_hir_id); + } + } + } + + fn reset_conditional_checker(&mut self, conditional_checkers: HashSet) { + for checker in conditional_checkers { + if checker.check_type.is_safe_to_expect() { + self.checked_exprs.remove(&checker.checked_expr_hir_id); + } + self.conditional_checker.remove(&checker); } + } + + /// Process conditional expressions to determine if they should halt execution. + fn handle_if_expressions(&mut self) { + self.conditional_checker.iter().for_each(|checker| { + if checker.check_type.should_halt_execution() { + println!("Halt: {:?}", checker.checked_expr_hir_id); + self.checked_exprs.insert(checker.checked_expr_hir_id); + } + }); + } + + fn is_literal_or_composed_of_literals(&self, expr: &Expr<'_>) -> bool { + let mut stack = vec![expr]; - impl<'tcx> Visitor<'tcx> for UnsafeExpectVisitor { - fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { - if let ExprKind::MethodCall(path_segment, _, _, _) = &expr.kind { - if path_segment.ident.name == Symbol::intern("expect") { - self.has_expect = true; - self.has_expect_span.push(Some(expr.span)); + while let Some(current_expr) = stack.pop() { + match current_expr.kind { + ExprKind::Lit(_) => continue, // A literal is fine, continue processing. + ExprKind::Tup(elements) | ExprKind::Array(elements) => { + stack.extend(elements); + } + ExprKind::Struct(_, fields, _) => { + for field in fields { + stack.push(field.expr); } } - walk_expr(self, expr); + ExprKind::Repeat(element, _) => { + stack.push(element); + } + _ => return false, // If any element is not a literal or a compound of literals, return false. } } - let mut visitor = UnsafeExpectVisitor { - has_expect: false, - has_expect_span: Vec::new(), - }; + true // If the stack is emptied without finding a non-literal, all elements are literals. + } +} - walk_expr(&mut visitor, body.value); +impl<'a, 'tcx> Visitor<'tcx> for UnsafeExpectVisitor<'a, 'tcx> { + fn visit_local(&mut self, local: &'tcx Local<'tcx>) { + if_chain! { + if let Some(init) = local.init; + if let ExprKind::Call(func, args) = init.kind; + if let ExprKind::Path(QPath::Resolved(_, path)) = func.kind; + then { + let is_some_or_ok = path.segments.iter().any(|segment| + matches!(segment.ident.name, sym::Some | sym::Ok) + ); + let all_literals = args.iter().all(|arg| self.is_literal_or_composed_of_literals(arg)); + if is_some_or_ok && all_literals { + self.checked_exprs.insert(local.pat.hir_id); + } + } + } + } + + fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { + // If we are inside an `if` or `if let` expression, we analyze its body + if !self.conditional_checker.is_empty() { + match &expr.kind { + ExprKind::Ret(..) => { + println!("Ret"); + self.handle_if_expressions(); + } + ExprKind::Call(func, _) if self.is_panic_inducing_call(func) => { + self.handle_if_expressions() + } + _ => {} + } + } + + // Find `if` or `if let` expressions + if let Some(higher::IfOrIfLet { + cond, + then: if_expr, + r#else: _, + }) = higher::IfOrIfLet::hir(expr) + { + // If we are interested in the condition (if it is a CheckType) we traverse the body. + let conditional_checker = ConditionalChecker::from_expression(cond); + self.set_conditional_checker(&conditional_checker); + walk_expr(self, if_expr); + self.reset_conditional_checker(conditional_checker); + return; + } - if visitor.has_expect { - visitor.has_expect_span.iter().for_each(|span| { - if let Some(span) = span { + // If we find an unsafe `expect`, we raise a warning + if_chain! { + if let ExprKind::MethodCall(path_segment, receiver, _, _) = &expr.kind; + if path_segment.ident.name == sym::expect; + then { + let receiver_hir_id = self.get_expect_info(receiver); + // If the receiver is `None`, then we asume that the `expect` is unsafe + let is_checked_safe = receiver_hir_id.map_or(false, |id| self.checked_exprs.contains(&id)); + if !is_checked_safe { span_lint_and_help( - cx, + self.cx, UNSAFE_EXPECT, - *span, + expr.span, LINT_MESSAGE, None, "Please, use a custom error instead of `expect`", ); } - }); + } } + + walk_expr(self, expr); + } +} + +impl<'tcx> LateLintPass<'tcx> for UnsafeExpect { + fn check_fn( + &mut self, + cx: &LateContext<'tcx>, + _: FnKind<'tcx>, + _: &'tcx FnDecl<'tcx>, + body: &'tcx Body<'tcx>, + span: Span, + _: LocalDefId, + ) { + // If the function comes from a macro expansion, we don't want to analyze it. + if span.from_expansion() { + return; + } + + let mut visitor = UnsafeExpectVisitor { + cx, + checked_exprs: HashSet::new(), + conditional_checker: HashSet::new(), + }; + + walk_expr(&mut visitor, body.value); } } diff --git a/detectors/unsafe-unwrap/src/lib.rs b/detectors/unsafe-unwrap/src/lib.rs index 771e6c11..63f0379c 100644 --- a/detectors/unsafe-unwrap/src/lib.rs +++ b/detectors/unsafe-unwrap/src/lib.rs @@ -1,18 +1,25 @@ #![feature(rustc_private)] +#![allow(clippy::enum_variant_names)] extern crate rustc_hir; extern crate rustc_span; +use std::{collections::HashSet, hash::Hash}; + +use if_chain::if_chain; +use rustc_hir::BinOpKind; use rustc_hir::{ + def::Res, def_id::LocalDefId, intravisit::{walk_expr, FnKind, Visitor}, - Body, Expr, ExprKind, FnDecl, + Body, Expr, ExprKind, FnDecl, HirId, Local, QPath, UnOp, }; use rustc_lint::{LateContext, LateLintPass}; -use rustc_span::{Span, Symbol}; -use scout_audit_clippy_utils::diagnostics::span_lint_and_help; +use rustc_span::{sym, Span, Symbol}; +use scout_audit_clippy_utils::{diagnostics::span_lint_and_help, higher}; const LINT_MESSAGE: &str = "Unsafe usage of `unwrap`"; +const PANIC_INDUCING_FUNCTIONS: [&str; 2] = ["panic", "bail"]; dylint_linting::declare_late_lint! { /// ### What it does @@ -57,53 +64,259 @@ dylint_linting::declare_late_lint! { } } -impl<'tcx> LateLintPass<'tcx> for UnsafeUnwrap { - fn check_fn( - &mut self, - cx: &LateContext<'tcx>, - _: FnKind<'tcx>, - _: &'tcx FnDecl<'tcx>, - body: &'tcx Body<'tcx>, - _: Span, - _: LocalDefId, - ) { - struct UnsafeUnwrapVisitor { - has_unwrap: bool, - has_unwrap_span: Vec>, +/// Represents the type of check performed on method call expressions to determine their safety or behavior. +#[derive(Clone, Copy, Hash, Eq, PartialEq)] +enum CheckType { + IsSome, + IsNone, + IsOk, + IsErr, +} + +impl CheckType { + fn from_method_name(name: Symbol) -> Option { + match name.as_str() { + "is_some" => Some(Self::IsSome), + "is_none" => Some(Self::IsNone), + "is_ok" => Some(Self::IsOk), + "is_err" => Some(Self::IsErr), + _ => None, + } + } + + fn inverse(self) -> Self { + match self { + Self::IsSome => Self::IsNone, + Self::IsNone => Self::IsSome, + Self::IsOk => Self::IsErr, + Self::IsErr => Self::IsOk, + } + } + + /// Determines if the check type implies execution should halt, such as in error conditions. + fn should_halt_execution(self) -> bool { + matches!(self, Self::IsNone | Self::IsErr) + } + + /// Determines if it is safe to unwrap the value without further checks, i.e., the value is present. + fn is_safe_to_unwrap(self) -> bool { + matches!(self, Self::IsSome | Self::IsOk) + } +} + +/// Represents a conditional checker that is used to analyze `if` or `if let` expressions. +#[derive(Clone, Copy, Hash, Eq, PartialEq)] +struct ConditionalChecker { + check_type: CheckType, + checked_expr_hir_id: HirId, +} + +impl ConditionalChecker { + /// Handle te condition of the `if` or `if let` expression. + fn handle_condition(condition: &Expr<'_>, inverse: bool) -> HashSet { + if_chain! { + if let ExprKind::MethodCall(path_segment, receiver, _, _) = condition.kind; + if let Some(check_type) = CheckType::from_method_name(path_segment.ident.name); + if let ExprKind::Path(QPath::Resolved(_, checked_expr_path)) = receiver.kind; + if let Res::Local(checked_expr_hir_id) = checked_expr_path.res; + then { + let check_type = if inverse { check_type.inverse() } else { check_type }; + return std::iter::once(Self { check_type, checked_expr_hir_id }).collect(); + } + } + HashSet::new() + } + + /// Constructs a ConditionalChecker from an expression if it matches a method call with a valid CheckType. + fn from_expression(condition: &Expr<'_>) -> HashSet { + match condition.kind { + // Single `not` expressions are supported + ExprKind::Unary(op, condition) => Self::handle_condition(condition, op == UnOp::Not), + // Multiple `or` expressions are supported + ExprKind::Binary(op, left_condition, right_condition) if op.node == BinOpKind::Or => { + let mut result = Self::from_expression(left_condition); + result.extend(Self::from_expression(right_condition)); + result + } + ExprKind::MethodCall(..) => Self::handle_condition(condition, false), + _ => HashSet::new(), } + } +} + +/// Main unsafe-unwrap visitor +struct UnsafeUnwrapVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + conditional_checker: HashSet, + checked_exprs: HashSet, +} + +impl UnsafeUnwrapVisitor<'_, '_> { + fn is_panic_inducing_call(&self, func: &Expr<'_>) -> bool { + if let ExprKind::Path(QPath::Resolved(_, path)) = &func.kind { + return PANIC_INDUCING_FUNCTIONS.iter().any(|&func| { + path.segments + .iter() + .any(|segment| segment.ident.name.as_str().contains(func)) + }); + } + false + } + + fn get_unwrap_info(&self, receiver: &Expr<'_>) -> Option { + if_chain! { + if let ExprKind::Path(QPath::Resolved(_, path)) = &receiver.kind; + if let Res::Local(hir_id) = path.res; + then { + return Some(hir_id); + } + } + None + } + + fn set_conditional_checker(&mut self, conditional_checkers: &HashSet) { + for checker in conditional_checkers { + self.conditional_checker.insert(*checker); + if checker.check_type.is_safe_to_unwrap() { + self.checked_exprs.insert(checker.checked_expr_hir_id); + } + } + } - impl<'tcx> Visitor<'tcx> for UnsafeUnwrapVisitor { - fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { - if let ExprKind::MethodCall(path_segment, _, _, _) = &expr.kind { - if path_segment.ident.name == Symbol::intern("unwrap") { - self.has_unwrap = true; - self.has_unwrap_span.push(Some(expr.span)); + fn reset_conditional_checker(&mut self, conditional_checkers: HashSet) { + for checker in conditional_checkers { + if checker.check_type.is_safe_to_unwrap() { + self.checked_exprs.remove(&checker.checked_expr_hir_id); + } + self.conditional_checker.remove(&checker); + } + } + + /// Process conditional expressions to determine if they should halt execution. + fn handle_if_expressions(&mut self) { + self.conditional_checker.iter().for_each(|checker| { + if checker.check_type.should_halt_execution() { + self.checked_exprs.insert(checker.checked_expr_hir_id); + } + }); + } + + fn is_literal_or_composed_of_literals(&self, expr: &Expr<'_>) -> bool { + let mut stack = vec![expr]; + + while let Some(current_expr) = stack.pop() { + match current_expr.kind { + ExprKind::Lit(_) => continue, // A literal is fine, continue processing. + ExprKind::Tup(elements) | ExprKind::Array(elements) => { + stack.extend(elements); + } + ExprKind::Struct(_, fields, _) => { + for field in fields { + stack.push(field.expr); } } - walk_expr(self, expr); + ExprKind::Repeat(element, _) => { + stack.push(element); + } + _ => return false, // If any element is not a literal or a compound of literals, return false. } } - let mut visitor = UnsafeUnwrapVisitor { - has_unwrap: false, - has_unwrap_span: Vec::new(), - }; + true // If the stack is emptied without finding a non-literal, all elements are literals. + } +} - walk_expr(&mut visitor, body.value); +impl<'a, 'tcx> Visitor<'tcx> for UnsafeUnwrapVisitor<'a, 'tcx> { + fn visit_local(&mut self, local: &'tcx Local<'tcx>) { + if_chain! { + if let Some(init) = local.init; + if let ExprKind::Call(func, args) = init.kind; + if let ExprKind::Path(QPath::Resolved(_, path)) = func.kind; + then { + let is_some_or_ok = path.segments.iter().any(|segment| + matches!(segment.ident.name, sym::Some | sym::Ok) + ); + let all_literals = args.iter().all(|arg| self.is_literal_or_composed_of_literals(arg)); + if is_some_or_ok && all_literals { + self.checked_exprs.insert(local.pat.hir_id); + } + } + } + } + + fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { + // If we are inside an `if` or `if let` expression, we analyze its body + if !self.conditional_checker.is_empty() { + match &expr.kind { + ExprKind::Ret(..) => self.handle_if_expressions(), + ExprKind::Call(func, _) if self.is_panic_inducing_call(func) => { + self.handle_if_expressions() + } + _ => {} + } + } - if visitor.has_unwrap { - visitor.has_unwrap_span.iter().for_each(|span| { - if let Some(span) = span { + // Find `if` or `if let` expressions + if let Some(higher::IfOrIfLet { + cond, + then: if_expr, + r#else: _, + }) = higher::IfOrIfLet::hir(expr) + { + // If we are interested in the condition (if it is a CheckType) we traverse the body. + let conditional_checker = ConditionalChecker::from_expression(cond); + self.set_conditional_checker(&conditional_checker); + walk_expr(self, if_expr); + self.reset_conditional_checker(conditional_checker); + return; + } + + // If we find an unsafe `unwrap`, we raise a warning + if_chain! { + if let ExprKind::MethodCall(path_segment, receiver, _, _) = &expr.kind; + if path_segment.ident.name == sym::unwrap; + then { + let receiver_hir_id = self.get_unwrap_info(receiver); + // If the receiver is `None`, then we asume that the `unwrap` is unsafe + let is_checked_safe = receiver_hir_id.map_or(false, |id| self.checked_exprs.contains(&id)); + if !is_checked_safe { span_lint_and_help( - cx, + self.cx, UNSAFE_UNWRAP, - *span, + expr.span, LINT_MESSAGE, None, "Please, use a custom error instead of `unwrap`", ); } - }); + } + } + + walk_expr(self, expr); + } +} + +impl<'tcx> LateLintPass<'tcx> for UnsafeUnwrap { + fn check_fn( + &mut self, + cx: &LateContext<'tcx>, + _: FnKind<'tcx>, + _: &'tcx FnDecl<'tcx>, + body: &'tcx Body<'tcx>, + span: Span, + _: LocalDefId, + ) { + // If the function comes from a macro expansion, we don't want to analyze it. + if span.from_expansion() { + return; } + + let mut visitor = UnsafeUnwrapVisitor { + cx, + checked_exprs: HashSet::new(), + conditional_checker: HashSet::new(), + }; + + walk_expr(&mut visitor, body.value); } } diff --git a/scripts/run-clippy.py b/scripts/run-clippy.py index 885661cd..5fe6789b 100644 --- a/scripts/run-clippy.py +++ b/scripts/run-clippy.py @@ -2,7 +2,7 @@ import os import time -from utils import print_errors, print_results, run_subprocess +from utils import print_errors, print_results, run_subprocess, is_rust_project GREEN = "\033[92m" ENDC = "\033[0m" @@ -18,8 +18,8 @@ def run_clippy(directories): continue print(f"\n{GREEN}Running clippy in {directory}:{ENDC}") - for root, _, files in os.walk(directory): - if "Cargo.toml" in files: + for root, _, _ in os.walk(directory): + if is_rust_project(root): start_time = time.time() returncode, _, stderr = run_subprocess( [ @@ -37,9 +37,6 @@ def run_clippy(directories): returncode, stderr, "clippy", root, time.time() - start_time ) - if root.startswith("test-cases"): - run_subprocess(["cargo", "clean"], cwd=root) - if returncode != 0: errors.append(root) diff --git a/scripts/run-fmt.py b/scripts/run-fmt.py index 5cfc3ef7..bc912426 100644 --- a/scripts/run-fmt.py +++ b/scripts/run-fmt.py @@ -2,7 +2,7 @@ import os import time -from utils import print_errors, print_results, run_subprocess +from utils import print_errors, print_results, run_subprocess, is_rust_project GREEN = "\033[92m" ENDC = "\033[0m" @@ -18,8 +18,8 @@ def run_fmt(directories): continue print(f"\n{GREEN}Checking format in {directory}:{ENDC}") - for root, _, files in os.walk(directory): - if "Cargo.toml" in files: + for root, _, _ in os.walk(directory): + if is_rust_project(root): start_time = time.time() returncode, _, stderr = run_subprocess( ["cargo", "fmt", "--all", "--check"], diff --git a/scripts/run-tests.py b/scripts/run-tests.py index 8fd11f43..759a056f 100644 --- a/scripts/run-tests.py +++ b/scripts/run-tests.py @@ -2,7 +2,13 @@ import argparse import time -from utils import parse_json_from_string, print_errors, print_results, run_subprocess +from utils import ( + parse_json_from_string, + print_errors, + print_results, + run_subprocess, + is_rust_project, +) RED = "\033[91m" GREEN = "\033[92m" @@ -17,8 +23,8 @@ def run_tests(detector): print(f"{RED}The specified directory does not exist.{ENDC}") return errors - for root, _, files in os.walk(directory): - if "Cargo.toml" in files: + for root, _, _ in os.walk(directory): + if is_rust_project(root): if run_unit_tests(root): errors.append(root) if run_integration_tests(detector, root): diff --git a/scripts/run-udeps.py b/scripts/run-udeps.py index 1d22a2e6..06dc535e 100644 --- a/scripts/run-udeps.py +++ b/scripts/run-udeps.py @@ -3,7 +3,7 @@ import subprocess import time -from utils import print_errors, print_results +from utils import print_errors, print_results, is_rust_project GREEN = "\033[92m" ENDC = "\033[0m" @@ -19,8 +19,8 @@ def run_udeps(directories): continue print(f"\n{GREEN}Checking unused dependencies in {directory}:{ENDC}") - for root, _, files in os.walk(directory): - if "Cargo.toml" in files: + for root, _, _ in os.walk(directory): + if is_rust_project(root): start_time = time.time() returncode, _, stderr = subprocess.run( ["cargo", "udeps"], cwd=root, capture_output=True, text=True diff --git a/scripts/utils.py b/scripts/utils.py index dcbddbec..2678db8f 100644 --- a/scripts/utils.py +++ b/scripts/utils.py @@ -1,4 +1,5 @@ import json +import os import subprocess from typing import Tuple, Optional @@ -8,6 +9,12 @@ ENDC = "\033[0m" +def is_rust_project(dir_path): + has_cargo_toml = os.path.isfile(os.path.join(dir_path, "Cargo.toml")) + has_lib_rs = os.path.isfile(os.path.join(dir_path, "src", "lib.rs")) + return has_cargo_toml and has_lib_rs + + def parse_json_from_string(console_output): json_start, json_end = None, None brace_count = 0 diff --git a/scripts/validate-detectors.py b/scripts/validate-detectors.py index 3dba4057..c1f1f732 100644 --- a/scripts/validate-detectors.py +++ b/scripts/validate-detectors.py @@ -24,9 +24,10 @@ def is_rust_project(dir_path): def check_for_extra_files(directory): """Ensure there are no unexpected files in a given directory.""" errors = [] + ignore_files = {"Cargo.lock", "Cargo.toml"} for item in os.listdir(directory): item_path = os.path.join(directory, item) - if os.path.isfile(item_path): + if os.path.isfile(item_path) and item not in ignore_files: errors.append(f"Unexpected file found: {item_path}") return errors @@ -70,22 +71,23 @@ def validate_example_structure(example_path, example_name): def validate_examples(detector_path, examples): """Validate the structure and naming convention of examples.""" errors = [] + ignore_dirs = {"target", ".cargo"} detector_name = os.path.basename(detector_path) example_suffixes = set() for example in examples: example_path = os.path.join(detector_path, example) - errors.extend(check_for_extra_files(example_path)) - errors.extend(validate_naming_convention(example, detector_name)) - suffix = example.split("-")[-1] - if suffix in example_suffixes: - errors.append( - f"Duplicate example number found in {detector_name}: {example}" - ) - else: - example_suffixes.add(suffix) - errors.extend(validate_example_structure(example_path, example)) - + if os.path.basename(example_path) not in ignore_dirs: + errors.extend(check_for_extra_files(example_path)) + errors.extend(validate_naming_convention(example, detector_name)) + suffix = example.split("-")[-1] + if suffix in example_suffixes: + errors.append( + f"Duplicate example number found in {detector_name}: {example}" + ) + else: + example_suffixes.add(suffix) + errors.extend(validate_example_structure(example_path, example)) return errors diff --git a/test-cases/assert-violation/Cargo.toml b/test-cases/assert-violation/Cargo.toml new file mode 100644 index 00000000..319daf6b --- /dev/null +++ b/test-cases/assert-violation/Cargo.toml @@ -0,0 +1,21 @@ +[workspace] +exclude = [".cargo", "target"] +members = ["assert-violation-*/*"] +resolver = "2" + +[workspace.dependencies] +soroban-sdk = { version = "=20.0.0" } + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/assert-violation/assert-violation-1/remediated-example/Cargo.toml b/test-cases/assert-violation/assert-violation-1/remediated-example/Cargo.toml index a2519d05..aabfe5cc 100644 --- a/test-cases/assert-violation/assert-violation-1/remediated-example/Cargo.toml +++ b/test-cases/assert-violation/assert-violation-1/remediated-example/Cargo.toml @@ -1,31 +1,16 @@ [package] +edition = "2021" name = "assert-violation-remediated-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = "=20.0.0" +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 - diff --git a/test-cases/assert-violation/assert-violation-1/vulnerable-example/Cargo.toml b/test-cases/assert-violation/assert-violation-1/vulnerable-example/Cargo.toml index 79f1f870..b3931c94 100644 --- a/test-cases/assert-violation/assert-violation-1/vulnerable-example/Cargo.toml +++ b/test-cases/assert-violation/assert-violation-1/vulnerable-example/Cargo.toml @@ -1,31 +1,16 @@ [package] +edition = "2021" name = "assert-violation-vulnerable-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = "=20.0.0" +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 - diff --git a/test-cases/avoid-core-mem-forget/Cargo.toml b/test-cases/avoid-core-mem-forget/Cargo.toml new file mode 100644 index 00000000..0674889d --- /dev/null +++ b/test-cases/avoid-core-mem-forget/Cargo.toml @@ -0,0 +1,21 @@ +[workspace] +exclude = [".cargo", "target"] +members = ["avoid-core-mem-forget-*/*"] +resolver = "2" + +[workspace.dependencies] +soroban-sdk = { version = "=20.0.0" } + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/avoid-core-mem-forget/avoid-core-mem-forget-1/remediated-example/Cargo.toml b/test-cases/avoid-core-mem-forget/avoid-core-mem-forget-1/remediated-example/Cargo.toml index b1f7b25a..d5b11867 100644 --- a/test-cases/avoid-core-mem-forget/avoid-core-mem-forget-1/remediated-example/Cargo.toml +++ b/test-cases/avoid-core-mem-forget/avoid-core-mem-forget-1/remediated-example/Cargo.toml @@ -1,30 +1,16 @@ [package] -name = "avoid-core-mem-forget-1-remediated" -version = "0.1.0" edition = "2021" +name = "avoid-core-mem-forget-remediated-1" +version = "0.1.0" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/avoid-core-mem-forget/avoid-core-mem-forget-1/vulnerable-example/Cargo.toml b/test-cases/avoid-core-mem-forget/avoid-core-mem-forget-1/vulnerable-example/Cargo.toml index dd1b5752..708b9a7f 100644 --- a/test-cases/avoid-core-mem-forget/avoid-core-mem-forget-1/vulnerable-example/Cargo.toml +++ b/test-cases/avoid-core-mem-forget/avoid-core-mem-forget-1/vulnerable-example/Cargo.toml @@ -1,30 +1,16 @@ [package] -name = "avoid-core-mem-forget-1-vulnerable" -version = "0.1.0" edition = "2021" +name = "avoid-core-mem-forget-vulnerable-1" +version = "0.1.0" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/avoid-panic-error/Cargo.toml b/test-cases/avoid-panic-error/Cargo.toml new file mode 100644 index 00000000..059f7eca --- /dev/null +++ b/test-cases/avoid-panic-error/Cargo.toml @@ -0,0 +1,21 @@ +[workspace] +exclude = [".cargo", "target"] +members = ["avoid-panic-error-*/*"] +resolver = "2" + +[workspace.dependencies] +soroban-sdk = { version = "=20.0.0" } + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/avoid-panic-error/avoid-panic-error-1/remediated-example/Cargo.toml b/test-cases/avoid-panic-error/avoid-panic-error-1/remediated-example/Cargo.toml index 42dfaf5d..7a77463b 100644 --- a/test-cases/avoid-panic-error/avoid-panic-error-1/remediated-example/Cargo.toml +++ b/test-cases/avoid-panic-error/avoid-panic-error-1/remediated-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "avoid-panic-error-remediated-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/avoid-panic-error/avoid-panic-error-1/vulnerable-example/Cargo.toml b/test-cases/avoid-panic-error/avoid-panic-error-1/vulnerable-example/Cargo.toml index b611b66f..fa0e74b7 100644 --- a/test-cases/avoid-panic-error/avoid-panic-error-1/vulnerable-example/Cargo.toml +++ b/test-cases/avoid-panic-error/avoid-panic-error-1/vulnerable-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "avoid-panic-error-vulnerable-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/avoid-unsafe-block/Cargo.toml b/test-cases/avoid-unsafe-block/Cargo.toml new file mode 100644 index 00000000..9abd5348 --- /dev/null +++ b/test-cases/avoid-unsafe-block/Cargo.toml @@ -0,0 +1,21 @@ +[workspace] +exclude = [".cargo", "target"] +members = ["avoid-unsafe-block-*/*"] +resolver = "2" + +[workspace.dependencies] +soroban-sdk = { version = "=20.0.0" } + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/avoid-unsafe-block/avoid-unsafe-block-1/remediated-example/Cargo.toml b/test-cases/avoid-unsafe-block/avoid-unsafe-block-1/remediated-example/Cargo.toml index edc47c18..a88a04a5 100644 --- a/test-cases/avoid-unsafe-block/avoid-unsafe-block-1/remediated-example/Cargo.toml +++ b/test-cases/avoid-unsafe-block/avoid-unsafe-block-1/remediated-example/Cargo.toml @@ -1,30 +1,16 @@ [package] -name = "avoid-unsafe-block-1-remediated" -version = "0.1.0" edition = "2021" +name = "avoid-unsafe-block-remediated-1" +version = "0.1.0" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/avoid-unsafe-block/avoid-unsafe-block-1/vulnerable-example/Cargo.toml b/test-cases/avoid-unsafe-block/avoid-unsafe-block-1/vulnerable-example/Cargo.toml index ab83c36e..10b4b428 100644 --- a/test-cases/avoid-unsafe-block/avoid-unsafe-block-1/vulnerable-example/Cargo.toml +++ b/test-cases/avoid-unsafe-block/avoid-unsafe-block-1/vulnerable-example/Cargo.toml @@ -1,30 +1,16 @@ [package] -name = "avoid-unsafe-block-1-vulnerable" -version = "0.1.0" edition = "2021" +name = "avoid-unsafe-block-vulnerable-1" +version = "0.1.0" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/divide-before-multiply/Cargo.toml b/test-cases/divide-before-multiply/Cargo.toml new file mode 100644 index 00000000..5b7f4963 --- /dev/null +++ b/test-cases/divide-before-multiply/Cargo.toml @@ -0,0 +1,21 @@ +[workspace] +exclude = [".cargo", "target"] +members = ["divide-before-multiply-*/*"] +resolver = "2" + +[workspace.dependencies] +soroban-sdk = { version = "=20.0.0" } + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/divide-before-multiply/divide-before-multiply-1/remediated-example/Cargo.toml b/test-cases/divide-before-multiply/divide-before-multiply-1/remediated-example/Cargo.toml index 53f396fe..da115e12 100644 --- a/test-cases/divide-before-multiply/divide-before-multiply-1/remediated-example/Cargo.toml +++ b/test-cases/divide-before-multiply/divide-before-multiply-1/remediated-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "divide-before-multiply-remediated-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/divide-before-multiply/divide-before-multiply-1/vulnerable-example/Cargo.toml b/test-cases/divide-before-multiply/divide-before-multiply-1/vulnerable-example/Cargo.toml index 78957f05..993b2fcd 100644 --- a/test-cases/divide-before-multiply/divide-before-multiply-1/vulnerable-example/Cargo.toml +++ b/test-cases/divide-before-multiply/divide-before-multiply-1/vulnerable-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "divide-before-multiply-vulnerable-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/divide-before-multiply/divide-before-multiply-2/remediated-example/Cargo.toml b/test-cases/divide-before-multiply/divide-before-multiply-2/remediated-example/Cargo.toml index acb9c316..62d3e70d 100644 --- a/test-cases/divide-before-multiply/divide-before-multiply-2/remediated-example/Cargo.toml +++ b/test-cases/divide-before-multiply/divide-before-multiply-2/remediated-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "divide-before-multiply-remediated-2" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/divide-before-multiply/divide-before-multiply-2/vulnerable-example/Cargo.toml b/test-cases/divide-before-multiply/divide-before-multiply-2/vulnerable-example/Cargo.toml index 6018990a..f4f86234 100644 --- a/test-cases/divide-before-multiply/divide-before-multiply-2/vulnerable-example/Cargo.toml +++ b/test-cases/divide-before-multiply/divide-before-multiply-2/vulnerable-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "divide-before-multiply-vulnerable-2" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/divide-before-multiply/divide-before-multiply-3/remediated-example/Cargo.toml b/test-cases/divide-before-multiply/divide-before-multiply-3/remediated-example/Cargo.toml index bd7eed0d..d2d4bf42 100644 --- a/test-cases/divide-before-multiply/divide-before-multiply-3/remediated-example/Cargo.toml +++ b/test-cases/divide-before-multiply/divide-before-multiply-3/remediated-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "divide-before-multiply-remediated-3" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/divide-before-multiply/divide-before-multiply-3/vulnerable-example/Cargo.toml b/test-cases/divide-before-multiply/divide-before-multiply-3/vulnerable-example/Cargo.toml index 557e2f32..53955cb7 100644 --- a/test-cases/divide-before-multiply/divide-before-multiply-3/vulnerable-example/Cargo.toml +++ b/test-cases/divide-before-multiply/divide-before-multiply-3/vulnerable-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "divide-before-multiply-vulnerable-3" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/dos-unbounded-operation/Cargo.toml b/test-cases/dos-unbounded-operation/Cargo.toml new file mode 100644 index 00000000..68a4495c --- /dev/null +++ b/test-cases/dos-unbounded-operation/Cargo.toml @@ -0,0 +1,21 @@ +[workspace] +exclude = [".cargo", "target"] +members = ["dos-unbounded-operation-*/*"] +resolver = "2" + +[workspace.dependencies] +soroban-sdk = { version = "=20.0.0" } + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/dos-unbounded-operation/dos-unbounded-operation-1/remediated-example/Cargo.toml b/test-cases/dos-unbounded-operation/dos-unbounded-operation-1/remediated-example/Cargo.toml index e14e166d..73ad69c7 100644 --- a/test-cases/dos-unbounded-operation/dos-unbounded-operation-1/remediated-example/Cargo.toml +++ b/test-cases/dos-unbounded-operation/dos-unbounded-operation-1/remediated-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "dos-unbounded-operation-remediated-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/dos-unbounded-operation/dos-unbounded-operation-1/vulnerable-example/Cargo.toml b/test-cases/dos-unbounded-operation/dos-unbounded-operation-1/vulnerable-example/Cargo.toml index 4bc5e539..8bdaff6a 100644 --- a/test-cases/dos-unbounded-operation/dos-unbounded-operation-1/vulnerable-example/Cargo.toml +++ b/test-cases/dos-unbounded-operation/dos-unbounded-operation-1/vulnerable-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "dos-unbounded-operation-vulnerable-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/dos-unbounded-operation/dos-unbounded-operation-2/remediated-example/Cargo.toml b/test-cases/dos-unbounded-operation/dos-unbounded-operation-2/remediated-example/Cargo.toml index 4f77f7e2..cbe0904b 100644 --- a/test-cases/dos-unbounded-operation/dos-unbounded-operation-2/remediated-example/Cargo.toml +++ b/test-cases/dos-unbounded-operation/dos-unbounded-operation-2/remediated-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "dos-unbounded-operation-remediated-2" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/dos-unbounded-operation/dos-unbounded-operation-2/vulnerable-example/Cargo.toml b/test-cases/dos-unbounded-operation/dos-unbounded-operation-2/vulnerable-example/Cargo.toml index 647591a7..328d643c 100644 --- a/test-cases/dos-unbounded-operation/dos-unbounded-operation-2/vulnerable-example/Cargo.toml +++ b/test-cases/dos-unbounded-operation/dos-unbounded-operation-2/vulnerable-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "dos-unbounded-operation-vulnerable-2" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/dos-unbounded-operation/dos-unbounded-operation-3/remediated-example/Cargo.toml b/test-cases/dos-unbounded-operation/dos-unbounded-operation-3/remediated-example/Cargo.toml index 07d29128..d0a065be 100644 --- a/test-cases/dos-unbounded-operation/dos-unbounded-operation-3/remediated-example/Cargo.toml +++ b/test-cases/dos-unbounded-operation/dos-unbounded-operation-3/remediated-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "dos-unbounded-operation-remediated-3" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/dos-unbounded-operation/dos-unbounded-operation-3/vulnerable-example/Cargo.toml b/test-cases/dos-unbounded-operation/dos-unbounded-operation-3/vulnerable-example/Cargo.toml index ef6f9a17..37b1b363 100644 --- a/test-cases/dos-unbounded-operation/dos-unbounded-operation-3/vulnerable-example/Cargo.toml +++ b/test-cases/dos-unbounded-operation/dos-unbounded-operation-3/vulnerable-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "dos-unbounded-operation-vulnerable-3" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/insufficiently-random-values/Cargo.toml b/test-cases/insufficiently-random-values/Cargo.toml new file mode 100644 index 00000000..a5301348 --- /dev/null +++ b/test-cases/insufficiently-random-values/Cargo.toml @@ -0,0 +1,21 @@ +[workspace] +exclude = [".cargo", "target"] +members = ["insufficiently-random-values-*/*"] +resolver = "2" + +[workspace.dependencies] +soroban-sdk = { version = "=20.0.0" } + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" 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 6e20f2a8..30b385f4 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,31 +1,17 @@ [package] +edition = "2021" name = "insufficiently-random-values-remediated-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = "=20.0.0" +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 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 5ade58d7..8ce272af 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,31 +1,17 @@ [package] +edition = "2021" name = "insufficiently-random-values-vulnerable-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = "=20.0.0" +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/iterators-over-indexing/Cargo.toml b/test-cases/iterators-over-indexing/Cargo.toml new file mode 100644 index 00000000..a2ed9201 --- /dev/null +++ b/test-cases/iterators-over-indexing/Cargo.toml @@ -0,0 +1,21 @@ +[workspace] +exclude = [".cargo", "target"] +members = ["iterators-over-indexing-*/*"] +resolver = "2" + +[workspace.dependencies] +soroban-sdk = { version = "=20.0.0" } + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/iterators-over-indexing/iterators-over-indexing-1/remediated-example/Cargo.toml b/test-cases/iterators-over-indexing/iterators-over-indexing-1/remediated-example/Cargo.toml index 85e09ffd..20b3cfbf 100644 --- a/test-cases/iterators-over-indexing/iterators-over-indexing-1/remediated-example/Cargo.toml +++ b/test-cases/iterators-over-indexing/iterators-over-indexing-1/remediated-example/Cargo.toml @@ -1,30 +1,16 @@ [package] -name = "iterators-over-indexing-vulnerable-1" -version = "0.1.0" edition = "2021" +name = "iterators-over-indexing-remediated-1" +version = "0.1.0" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = "20.0.0" +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/iterators-over-indexing/iterators-over-indexing-1/vulnerable-example/Cargo.toml b/test-cases/iterators-over-indexing/iterators-over-indexing-1/vulnerable-example/Cargo.toml index 85e09ffd..d03444a9 100644 --- a/test-cases/iterators-over-indexing/iterators-over-indexing-1/vulnerable-example/Cargo.toml +++ b/test-cases/iterators-over-indexing/iterators-over-indexing-1/vulnerable-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "iterators-over-indexing-vulnerable-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = "20.0.0" +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/overflow-check/Cargo.toml b/test-cases/overflow-check/Cargo.toml new file mode 100644 index 00000000..ff588478 --- /dev/null +++ b/test-cases/overflow-check/Cargo.toml @@ -0,0 +1,20 @@ +[workspace] +exclude = [".cargo", "target"] +members = ["overflow-check-*/*"] +resolver = "2" + +[workspace.dependencies] +soroban-sdk = { version = "=20.0.0" } + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/overflow-check/overflow-check-1/remediated-example/Cargo.toml b/test-cases/overflow-check/overflow-check-1/remediated-example/Cargo.toml index 45224611..b7835f5f 100644 --- a/test-cases/overflow-check/overflow-check-1/remediated-example/Cargo.toml +++ b/test-cases/overflow-check/overflow-check-1/remediated-example/Cargo.toml @@ -1,32 +1,20 @@ [package] +edition = "2021" name = "overflow-check-remediated-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = "=20.0.0" +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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] overflow-checks = true -inherits = "release" -debug-assertions = true diff --git a/test-cases/overflow-check/overflow-check-1/vulnerable-example/Cargo.toml b/test-cases/overflow-check/overflow-check-1/vulnerable-example/Cargo.toml index 536d3c4c..93fa7c17 100644 --- a/test-cases/overflow-check/overflow-check-1/vulnerable-example/Cargo.toml +++ b/test-cases/overflow-check/overflow-check-1/vulnerable-example/Cargo.toml @@ -1,31 +1,20 @@ [package] +edition = "2021" name = "overflow-check-vulnerable-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = "=20.0.0" +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, features = ["testutils"] } [features] testutils = ["soroban-sdk/testutils"] [profile.release] -opt-level = "z" overflow-checks = false -debug = 0 -strip = "symbols" -debug-assertions = false -panic = "abort" -codegen-units = 1 -lto = true - -[profile.release-with-logs] -inherits = "release" -debug-assertions = true diff --git a/test-cases/set-contract-storage/Cargo.toml b/test-cases/set-contract-storage/Cargo.toml new file mode 100644 index 00000000..4ed17155 --- /dev/null +++ b/test-cases/set-contract-storage/Cargo.toml @@ -0,0 +1,21 @@ +[workspace] +exclude = [".cargo", "target"] +members = ["set-contract-storage-*/*"] +resolver = "2" + +[workspace.dependencies] +soroban-sdk = { version = "=20.0.0" } + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/set-contract-storage/set-contract-storage-1/remediated-example/Cargo.toml b/test-cases/set-contract-storage/set-contract-storage-1/remediated-example/Cargo.toml index 011fe482..2930db92 100644 --- a/test-cases/set-contract-storage/set-contract-storage-1/remediated-example/Cargo.toml +++ b/test-cases/set-contract-storage/set-contract-storage-1/remediated-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "set-contract-storage-remediated-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/set-contract-storage/set-contract-storage-1/vulnerable-example/Cargo.toml b/test-cases/set-contract-storage/set-contract-storage-1/vulnerable-example/Cargo.toml index bfaf4350..48765b8c 100644 --- a/test-cases/set-contract-storage/set-contract-storage-1/vulnerable-example/Cargo.toml +++ b/test-cases/set-contract-storage/set-contract-storage-1/vulnerable-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "set-contract-storage-vulnerable-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/set-contract-storage/set-contract-storage-2/remediated-example/Cargo.toml b/test-cases/set-contract-storage/set-contract-storage-2/remediated-example/Cargo.toml index 8daa6a30..469bce4b 100644 --- a/test-cases/set-contract-storage/set-contract-storage-2/remediated-example/Cargo.toml +++ b/test-cases/set-contract-storage/set-contract-storage-2/remediated-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "set-contract-storage-remediated-2" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/set-contract-storage/set-contract-storage-2/vulnerable-example/Cargo.toml b/test-cases/set-contract-storage/set-contract-storage-2/vulnerable-example/Cargo.toml index f8433cd1..e588c294 100644 --- a/test-cases/set-contract-storage/set-contract-storage-2/vulnerable-example/Cargo.toml +++ b/test-cases/set-contract-storage/set-contract-storage-2/vulnerable-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "set-contract-storage-vulnerable-2" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/set-contract-storage/set-contract-storage-3/remediated-example/Cargo.toml b/test-cases/set-contract-storage/set-contract-storage-3/remediated-example/Cargo.toml index 7f6e4413..bde6f22d 100644 --- a/test-cases/set-contract-storage/set-contract-storage-3/remediated-example/Cargo.toml +++ b/test-cases/set-contract-storage/set-contract-storage-3/remediated-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "set-contract-storage-remediated-3" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/set-contract-storage/set-contract-storage-3/vulnerable-example/Cargo.toml b/test-cases/set-contract-storage/set-contract-storage-3/vulnerable-example/Cargo.toml index b5ae6c2d..74b35b64 100644 --- a/test-cases/set-contract-storage/set-contract-storage-3/vulnerable-example/Cargo.toml +++ b/test-cases/set-contract-storage/set-contract-storage-3/vulnerable-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "set-contract-storage-vulnerable-3" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/set-contract-storage/set-contract-storage-4/remediated-example/Cargo.toml b/test-cases/set-contract-storage/set-contract-storage-4/remediated-example/Cargo.toml index a9aede4e..6a6f8e4f 100644 --- a/test-cases/set-contract-storage/set-contract-storage-4/remediated-example/Cargo.toml +++ b/test-cases/set-contract-storage/set-contract-storage-4/remediated-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "set-contract-storage-remediated-4" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/set-contract-storage/set-contract-storage-4/vulnerable-example/Cargo.toml b/test-cases/set-contract-storage/set-contract-storage-4/vulnerable-example/Cargo.toml index ee4173c6..2e010c67 100644 --- a/test-cases/set-contract-storage/set-contract-storage-4/vulnerable-example/Cargo.toml +++ b/test-cases/set-contract-storage/set-contract-storage-4/vulnerable-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "set-contract-storage-vulnerable-4" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/soroban-version/Cargo.toml b/test-cases/soroban-version/Cargo.toml new file mode 100644 index 00000000..de5686c5 --- /dev/null +++ b/test-cases/soroban-version/Cargo.toml @@ -0,0 +1,21 @@ +[workspace] +exclude = [".cargo", "target"] +members = ["soroban-version-*/*"] +resolver = "2" + +[workspace.dependencies] +soroban-sdk = { version = "=20.0.0" } + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/soroban-version/soroban-version-1/remediated-example/Cargo.toml b/test-cases/soroban-version/soroban-version-1/remediated-example/Cargo.toml index 2bfb6108..b82bc0ab 100644 --- a/test-cases/soroban-version/soroban-version-1/remediated-example/Cargo.toml +++ b/test-cases/soroban-version/soroban-version-1/remediated-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "soroban-version-remediated-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/soroban-version/soroban-version-1/vulnerable-example/Cargo.toml b/test-cases/soroban-version/soroban-version-1/vulnerable-example/Cargo.toml index c5771258..9d9efe06 100644 --- a/test-cases/soroban-version/soroban-version-1/vulnerable-example/Cargo.toml +++ b/test-cases/soroban-version/soroban-version-1/vulnerable-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "soroban-version-vulnerable-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/unprotected-mapping-operation/Cargo.toml b/test-cases/unprotected-mapping-operation/Cargo.toml new file mode 100644 index 00000000..46ee0cfb --- /dev/null +++ b/test-cases/unprotected-mapping-operation/Cargo.toml @@ -0,0 +1,21 @@ +[workspace] +exclude = [".cargo", "target"] +members = ["unprotected-mapping-operation-*/*"] +resolver = "2" + +[workspace.dependencies] +soroban-sdk = { version = "=20.0.0" } + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/unprotected-mapping-operation/unprotected-mapping-operation-1/remediated-example/Cargo.toml b/test-cases/unprotected-mapping-operation/unprotected-mapping-operation-1/remediated-example/Cargo.toml index b2c5ac07..65936dfe 100644 --- a/test-cases/unprotected-mapping-operation/unprotected-mapping-operation-1/remediated-example/Cargo.toml +++ b/test-cases/unprotected-mapping-operation/unprotected-mapping-operation-1/remediated-example/Cargo.toml @@ -8,24 +8,10 @@ version = "0.1.0" crate-type = ["cdylib"] [dependencies] -soroban-sdk = "=20.0.0" +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, features = ["testutils"] } [features] testutils = ["soroban-sdk/testutils"] - -[profile.release] -codegen-units = 1 -debug = 0 -debug-assertions = false -lto = true -opt-level = "z" -overflow-checks = true -panic = "abort" -strip = "symbols" - -[profile.release-with-logs] -debug-assertions = true -inherits = "release" diff --git a/test-cases/unprotected-mapping-operation/unprotected-mapping-operation-1/vulnerable-example/Cargo.toml b/test-cases/unprotected-mapping-operation/unprotected-mapping-operation-1/vulnerable-example/Cargo.toml index ada3e584..f4dd6328 100644 --- a/test-cases/unprotected-mapping-operation/unprotected-mapping-operation-1/vulnerable-example/Cargo.toml +++ b/test-cases/unprotected-mapping-operation/unprotected-mapping-operation-1/vulnerable-example/Cargo.toml @@ -8,24 +8,10 @@ version = "0.1.0" crate-type = ["cdylib"] [dependencies] -soroban-sdk = "=20.0.0" +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, features = ["testutils"] } [features] testutils = ["soroban-sdk/testutils"] - -[profile.release] -codegen-units = 1 -debug = 0 -debug-assertions = false -lto = true -opt-level = "z" -overflow-checks = true -panic = "abort" -strip = "symbols" - -[profile.release-with-logs] -debug-assertions = true -inherits = "release" diff --git a/test-cases/unprotected-mapping-operation/unprotected-mapping-operation-2/remediated-example/Cargo.toml b/test-cases/unprotected-mapping-operation/unprotected-mapping-operation-2/remediated-example/Cargo.toml index dfa714a7..fae91814 100644 --- a/test-cases/unprotected-mapping-operation/unprotected-mapping-operation-2/remediated-example/Cargo.toml +++ b/test-cases/unprotected-mapping-operation/unprotected-mapping-operation-2/remediated-example/Cargo.toml @@ -8,24 +8,10 @@ version = "0.1.0" crate-type = ["cdylib"] [dependencies] -soroban-sdk = "=20.0.0" +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, features = ["testutils"] } [features] testutils = ["soroban-sdk/testutils"] - -[profile.release] -codegen-units = 1 -debug = 0 -debug-assertions = false -lto = true -opt-level = "z" -overflow-checks = true -panic = "abort" -strip = "symbols" - -[profile.release-with-logs] -debug-assertions = true -inherits = "release" diff --git a/test-cases/unprotected-mapping-operation/unprotected-mapping-operation-2/vulnerable-example/Cargo.toml b/test-cases/unprotected-mapping-operation/unprotected-mapping-operation-2/vulnerable-example/Cargo.toml index 3b409b54..f3b66e08 100644 --- a/test-cases/unprotected-mapping-operation/unprotected-mapping-operation-2/vulnerable-example/Cargo.toml +++ b/test-cases/unprotected-mapping-operation/unprotected-mapping-operation-2/vulnerable-example/Cargo.toml @@ -8,24 +8,10 @@ version = "0.1.0" crate-type = ["cdylib"] [dependencies] -soroban-sdk = "=20.0.0" +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, features = ["testutils"] } [features] testutils = ["soroban-sdk/testutils"] - -[profile.release] -codegen-units = 1 -debug = 0 -debug-assertions = false -lto = true -opt-level = "z" -overflow-checks = true -panic = "abort" -strip = "symbols" - -[profile.release-with-logs] -debug-assertions = true -inherits = "release" diff --git a/test-cases/unprotected-update-current-contract-wasm/Cargo.toml b/test-cases/unprotected-update-current-contract-wasm/Cargo.toml new file mode 100644 index 00000000..399bb063 --- /dev/null +++ b/test-cases/unprotected-update-current-contract-wasm/Cargo.toml @@ -0,0 +1,21 @@ +[workspace] +exclude = [".cargo", "target"] +members = ["unprotected-update-current-contract-wasm-*/*"] +resolver = "2" + +[workspace.dependencies] +soroban-sdk = { version = "=20.0.0" } + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/unprotected-update-current-contract-wasm/unprotected-update-current-contract-wasm-1/remediated-example/Cargo.toml b/test-cases/unprotected-update-current-contract-wasm/unprotected-update-current-contract-wasm-1/remediated-example/Cargo.toml index 9fb5cf8e..4c498c24 100644 --- a/test-cases/unprotected-update-current-contract-wasm/unprotected-update-current-contract-wasm-1/remediated-example/Cargo.toml +++ b/test-cases/unprotected-update-current-contract-wasm/unprotected-update-current-contract-wasm-1/remediated-example/Cargo.toml @@ -8,24 +8,10 @@ version = "0.1.0" crate-type = ["cdylib"] [dependencies] -soroban-sdk = "=20.0.0" +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, features = ["testutils"] } [features] testutils = ["soroban-sdk/testutils"] - -[profile.release] -codegen-units = 1 -debug = 0 -debug-assertions = false -lto = true -opt-level = "z" -overflow-checks = true -panic = "abort" -strip = "symbols" - -[profile.release-with-logs] -debug-assertions = true -inherits = "release" diff --git a/test-cases/unprotected-update-current-contract-wasm/unprotected-update-current-contract-wasm-1/vulnerable-example/Cargo.toml b/test-cases/unprotected-update-current-contract-wasm/unprotected-update-current-contract-wasm-1/vulnerable-example/Cargo.toml index 30cebce4..23a69ea8 100644 --- a/test-cases/unprotected-update-current-contract-wasm/unprotected-update-current-contract-wasm-1/vulnerable-example/Cargo.toml +++ b/test-cases/unprotected-update-current-contract-wasm/unprotected-update-current-contract-wasm-1/vulnerable-example/Cargo.toml @@ -8,24 +8,10 @@ version = "0.1.0" crate-type = ["cdylib"] [dependencies] -soroban-sdk = "=20.0.0" +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, features = ["testutils"] } [features] testutils = ["soroban-sdk/testutils"] - -[profile.release] -codegen-units = 1 -debug = 0 -debug-assertions = false -lto = true -opt-level = "z" -overflow-checks = true -panic = "abort" -strip = "symbols" - -[profile.release-with-logs] -debug-assertions = true -inherits = "release" diff --git a/test-cases/unsafe-expect/Cargo.toml b/test-cases/unsafe-expect/Cargo.toml new file mode 100644 index 00000000..a163f8ba --- /dev/null +++ b/test-cases/unsafe-expect/Cargo.toml @@ -0,0 +1,21 @@ +[workspace] +exclude = [".cargo", "target"] +members = ["unsafe-expect-*/*"] +resolver = "2" + +[workspace.dependencies] +soroban-sdk = { version = "=20.0.0" } + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/unsafe-expect/unsafe-expect-1/remediated-example/Cargo.toml b/test-cases/unsafe-expect/unsafe-expect-1/remediated-example/Cargo.toml index 7c42bb70..dfd4e0d9 100644 --- a/test-cases/unsafe-expect/unsafe-expect-1/remediated-example/Cargo.toml +++ b/test-cases/unsafe-expect/unsafe-expect-1/remediated-example/Cargo.toml @@ -1,31 +1,16 @@ [package] +edition = "2021" name = "unsafe-expect-remediated-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 - diff --git a/test-cases/unsafe-expect/unsafe-expect-1/vulnerable-example/Cargo.toml b/test-cases/unsafe-expect/unsafe-expect-1/vulnerable-example/Cargo.toml index ad17528b..6268a10d 100644 --- a/test-cases/unsafe-expect/unsafe-expect-1/vulnerable-example/Cargo.toml +++ b/test-cases/unsafe-expect/unsafe-expect-1/vulnerable-example/Cargo.toml @@ -1,31 +1,16 @@ [package] +edition = "2021" name = "unsafe-expect-vulnerable-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 - diff --git a/test-cases/unsafe-expect/unsafe-expect-2/remediated-example/Cargo.toml b/test-cases/unsafe-expect/unsafe-expect-2/remediated-example/Cargo.toml new file mode 100644 index 00000000..450051f9 --- /dev/null +++ b/test-cases/unsafe-expect/unsafe-expect-2/remediated-example/Cargo.toml @@ -0,0 +1,30 @@ +[package] +edition = "2021" +name = "unsafe-expect-remediated-2" +version = "0.1.0" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +soroban-sdk = { version = "=20.0.0" } + +[dev_dependencies] +soroban-sdk = { version = "=20.0.0", features = ["testutils"] } + +[features] +testutils = ["soroban-sdk/testutils"] + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/unsafe-expect/unsafe-expect-2/remediated-example/src/lib.rs b/test-cases/unsafe-expect/unsafe-expect-2/remediated-example/src/lib.rs new file mode 100644 index 00000000..7a5349c9 --- /dev/null +++ b/test-cases/unsafe-expect/unsafe-expect-2/remediated-example/src/lib.rs @@ -0,0 +1,90 @@ +use soroban_sdk::{contract, contractimpl, contracttype, symbol_short, Address, Env, Map, Symbol}; + +#[contract] +pub struct UnsafeExpect; + +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct State { + balances: Map, +} +const STATE: Symbol = symbol_short!("STATE"); + +#[contractimpl] +impl UnsafeExpect { + pub fn set_balance(env: Env, address: Address, balance: i128) -> State { + // Only the owner can set the balance. + address.require_auth(); + + // Get the current state. + let mut state = Self::get_state(env.clone()); + + // Set the new account to have total supply if it doesn't exist. + if !state.balances.contains_key(address.clone()) { + state.balances.set(address, balance); + // Save the state. + env.storage().persistent().set(&STATE, &state); + } + + state + } + + // Returns the balance of a given account. + pub fn balance_of(env: Env, owner: Address) -> i128 { + let state = Self::get_state(env); + let balance = state.balances.get(owner); + if balance.is_none() { + return 0; + } + balance.expect("could not get balance") + } + + /// Return the current state. + pub fn get_state(env: Env) -> State { + env.storage().persistent().get(&STATE).unwrap_or(State { + balances: Map::new(&env), + }) + } +} + +#[cfg(test)] +const TOTAL_SUPPLY: i128 = 200; + +#[cfg(test)] +mod tests { + + use soroban_sdk::Env; + + use crate::{UnsafeExpect, UnsafeExpectClient, TOTAL_SUPPLY}; + + #[test] + fn balance_of_works() { + // Given + let env = Env::default(); + let contract_id = env.register_contract(None, UnsafeExpect); + let client = UnsafeExpectClient::new(&env, &contract_id); + + // When + client + .mock_all_auths() + .set_balance(&contract_id, &TOTAL_SUPPLY); + + // Then + let balance = client.balance_of(&contract_id); + assert_eq!(TOTAL_SUPPLY, balance); + } + + #[test] + fn balance_of_unwrap_works() { + // Given + let env = Env::default(); + let contract_id = env.register_contract(None, UnsafeExpect); + let client = UnsafeExpectClient::new(&env, &contract_id); + + // When - Balance not set + + // Then + let balance = client.balance_of(&contract_id); + assert_eq!(0, balance); + } +} diff --git a/test-cases/unsafe-expect/unsafe-expect-2/vulnerable-example/Cargo.toml b/test-cases/unsafe-expect/unsafe-expect-2/vulnerable-example/Cargo.toml new file mode 100644 index 00000000..357a33e9 --- /dev/null +++ b/test-cases/unsafe-expect/unsafe-expect-2/vulnerable-example/Cargo.toml @@ -0,0 +1,30 @@ +[package] +edition = "2021" +name = "unsafe-expect-vulnerable-2" +version = "0.1.0" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +soroban-sdk = { version = "=20.0.0" } + +[dev_dependencies] +soroban-sdk = { version = "=20.0.0", features = ["testutils"] } + +[features] +testutils = ["soroban-sdk/testutils"] + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/unsafe-expect/unsafe-expect-2/vulnerable-example/src/lib.rs b/test-cases/unsafe-expect/unsafe-expect-2/vulnerable-example/src/lib.rs new file mode 100644 index 00000000..e3d8601f --- /dev/null +++ b/test-cases/unsafe-expect/unsafe-expect-2/vulnerable-example/src/lib.rs @@ -0,0 +1,83 @@ +use soroban_sdk::{contract, contractimpl, contracttype, symbol_short, Address, Env, Map, Symbol}; + +#[contract] +pub struct UnsafeExpect; + +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct State { + balances: Map, +} +const STATE: Symbol = symbol_short!("STATE"); + +#[contractimpl] +impl UnsafeExpect { + pub fn set_balance(env: Env, address: Address, balance: i128) -> State { + // Get the current state. + let mut state = Self::get_state(env.clone()); + + // Set the new account to have total supply if it doesn't exist. + if !state.balances.contains_key(address.clone()) { + state.balances.set(address, balance); + // Save the state. + env.storage().persistent().set(&STATE, &state); + } + + state + } + + // Returns the balance of a given account. + pub fn balance_of(env: Env, owner: Address) -> i128 { + let state = Self::get_state(env); + state.balances.get(owner).expect("could not get balance") + } + + /// Return the current state. + pub fn get_state(env: Env) -> State { + env.storage().persistent().get(&STATE).unwrap_or(State { + balances: Map::new(&env), + }) + } +} + +#[cfg(test)] +const TOTAL_SUPPLY: i128 = 200; + +#[cfg(test)] +mod tests { + + use soroban_sdk::Env; + + use crate::{UnsafeExpect, UnsafeExpectClient, TOTAL_SUPPLY}; + + #[test] + fn balance_of_works() { + // Given + let env = Env::default(); + let contract_id = env.register_contract(None, UnsafeExpect); + let client = UnsafeExpectClient::new(&env, &contract_id); + + // When + client.set_balance(&contract_id, &TOTAL_SUPPLY); + + // Then + let balance = client.balance_of(&contract_id); + assert_eq!(TOTAL_SUPPLY, balance); + } + + #[test] + #[should_panic(expected = "could not get balance")] + fn balance_of_expect_works() { + // Given + let env = Env::default(); + let contract_id = env.register_contract(None, UnsafeExpect); + let client = UnsafeExpectClient::new(&env, &contract_id); + + // When - Balance not set + + // Then + let _balance = client.balance_of(&contract_id); + + // Test should panic + } +} diff --git a/test-cases/unsafe-expect/unsafe-expect-3/remediated-example/Cargo.toml b/test-cases/unsafe-expect/unsafe-expect-3/remediated-example/Cargo.toml new file mode 100644 index 00000000..2be23bf5 --- /dev/null +++ b/test-cases/unsafe-expect/unsafe-expect-3/remediated-example/Cargo.toml @@ -0,0 +1,30 @@ +[package] +edition = "2021" +name = "unsafe-expect-remediated-3" +version = "0.1.0" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +soroban-sdk = { version = "=20.0.0" } + +[dev_dependencies] +soroban-sdk = { version = "=20.0.0", features = ["testutils"] } + +[features] +testutils = ["soroban-sdk/testutils"] + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/unsafe-expect/unsafe-expect-3/remediated-example/src/lib.rs b/test-cases/unsafe-expect/unsafe-expect-3/remediated-example/src/lib.rs new file mode 100644 index 00000000..e764f8b0 --- /dev/null +++ b/test-cases/unsafe-expect/unsafe-expect-3/remediated-example/src/lib.rs @@ -0,0 +1,91 @@ +use soroban_sdk::{contract, contractimpl, contracttype, symbol_short, Address, Env, Map, Symbol}; + +#[contract] +pub struct UnsafeExpect; + +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct State { + balances: Map, +} +const STATE: Symbol = symbol_short!("STATE"); + +#[contractimpl] +impl UnsafeExpect { + pub fn set_balance(env: Env, address: Address, balance: i128) -> State { + // Only the owner can set the balance. + address.require_auth(); + + // Get the current state. + let mut state = Self::get_state(env.clone()); + + // Set the new account to have total supply if it doesn't exist. + if !state.balances.contains_key(address.clone()) { + state.balances.set(address, balance); + // Save the state. + env.storage().persistent().set(&STATE, &state); + } + + state + } + + // Returns the balance of a given account. + pub fn balance_of(env: Env, owner: Address) -> i128 { + let state = Self::get_state(env); + let balance = state.balances.get(owner); + let mut return_value = 0; + if balance.is_some() { + return_value = balance.expect("could not get balance"); + } + return_value + } + + /// Return the current state. + pub fn get_state(env: Env) -> State { + env.storage().persistent().get(&STATE).unwrap_or(State { + balances: Map::new(&env), + }) + } +} + +#[cfg(test)] +const TOTAL_SUPPLY: i128 = 200; + +#[cfg(test)] +mod tests { + + use soroban_sdk::Env; + + use crate::{UnsafeExpect, UnsafeExpectClient, TOTAL_SUPPLY}; + + #[test] + fn balance_of_works() { + // Given + let env = Env::default(); + let contract_id = env.register_contract(None, UnsafeExpect); + let client = UnsafeExpectClient::new(&env, &contract_id); + + // When + client + .mock_all_auths() + .set_balance(&contract_id, &TOTAL_SUPPLY); + + // Then + let balance = client.balance_of(&contract_id); + assert_eq!(TOTAL_SUPPLY, balance); + } + + #[test] + fn balance_of_unwrap_works() { + // Given + let env = Env::default(); + let contract_id = env.register_contract(None, UnsafeExpect); + let client = UnsafeExpectClient::new(&env, &contract_id); + + // When - Balance not set + + // Then + let balance = client.balance_of(&contract_id); + assert_eq!(0, balance); + } +} diff --git a/test-cases/unsafe-expect/unsafe-expect-3/vulnerable-example/Cargo.toml b/test-cases/unsafe-expect/unsafe-expect-3/vulnerable-example/Cargo.toml new file mode 100644 index 00000000..af83ecbb --- /dev/null +++ b/test-cases/unsafe-expect/unsafe-expect-3/vulnerable-example/Cargo.toml @@ -0,0 +1,30 @@ +[package] +edition = "2021" +name = "unsafe-expect-vulnerable-3" +version = "0.1.0" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +soroban-sdk = { version = "=20.0.0" } + +[dev_dependencies] +soroban-sdk = { version = "=20.0.0", features = ["testutils"] } + +[features] +testutils = ["soroban-sdk/testutils"] + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/unsafe-expect/unsafe-expect-3/vulnerable-example/src/lib.rs b/test-cases/unsafe-expect/unsafe-expect-3/vulnerable-example/src/lib.rs new file mode 100644 index 00000000..e3d8601f --- /dev/null +++ b/test-cases/unsafe-expect/unsafe-expect-3/vulnerable-example/src/lib.rs @@ -0,0 +1,83 @@ +use soroban_sdk::{contract, contractimpl, contracttype, symbol_short, Address, Env, Map, Symbol}; + +#[contract] +pub struct UnsafeExpect; + +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct State { + balances: Map, +} +const STATE: Symbol = symbol_short!("STATE"); + +#[contractimpl] +impl UnsafeExpect { + pub fn set_balance(env: Env, address: Address, balance: i128) -> State { + // Get the current state. + let mut state = Self::get_state(env.clone()); + + // Set the new account to have total supply if it doesn't exist. + if !state.balances.contains_key(address.clone()) { + state.balances.set(address, balance); + // Save the state. + env.storage().persistent().set(&STATE, &state); + } + + state + } + + // Returns the balance of a given account. + pub fn balance_of(env: Env, owner: Address) -> i128 { + let state = Self::get_state(env); + state.balances.get(owner).expect("could not get balance") + } + + /// Return the current state. + pub fn get_state(env: Env) -> State { + env.storage().persistent().get(&STATE).unwrap_or(State { + balances: Map::new(&env), + }) + } +} + +#[cfg(test)] +const TOTAL_SUPPLY: i128 = 200; + +#[cfg(test)] +mod tests { + + use soroban_sdk::Env; + + use crate::{UnsafeExpect, UnsafeExpectClient, TOTAL_SUPPLY}; + + #[test] + fn balance_of_works() { + // Given + let env = Env::default(); + let contract_id = env.register_contract(None, UnsafeExpect); + let client = UnsafeExpectClient::new(&env, &contract_id); + + // When + client.set_balance(&contract_id, &TOTAL_SUPPLY); + + // Then + let balance = client.balance_of(&contract_id); + assert_eq!(TOTAL_SUPPLY, balance); + } + + #[test] + #[should_panic(expected = "could not get balance")] + fn balance_of_expect_works() { + // Given + let env = Env::default(); + let contract_id = env.register_contract(None, UnsafeExpect); + let client = UnsafeExpectClient::new(&env, &contract_id); + + // When - Balance not set + + // Then + let _balance = client.balance_of(&contract_id); + + // Test should panic + } +} diff --git a/test-cases/unsafe-expect/unsafe-expect-4/remediated-example/Cargo.toml b/test-cases/unsafe-expect/unsafe-expect-4/remediated-example/Cargo.toml new file mode 100644 index 00000000..72ad8424 --- /dev/null +++ b/test-cases/unsafe-expect/unsafe-expect-4/remediated-example/Cargo.toml @@ -0,0 +1,30 @@ +[package] +edition = "2021" +name = "unsafe-expect-remediated-4" +version = "0.1.0" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +soroban-sdk = { version = "=20.0.0" } + +[dev_dependencies] +soroban-sdk = { version = "=20.0.0", features = ["testutils"] } + +[features] +testutils = ["soroban-sdk/testutils"] + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/unsafe-expect/unsafe-expect-4/remediated-example/src/lib.rs b/test-cases/unsafe-expect/unsafe-expect-4/remediated-example/src/lib.rs new file mode 100644 index 00000000..c7b1c42d --- /dev/null +++ b/test-cases/unsafe-expect/unsafe-expect-4/remediated-example/src/lib.rs @@ -0,0 +1,98 @@ +use soroban_sdk::{contract, contractimpl, contracttype, symbol_short, Address, Env, Map, Symbol}; + +#[contract] +pub struct UnsafeExpect; + +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct State { + balances: Map, +} +const STATE: Symbol = symbol_short!("STATE"); + +#[contractimpl] +impl UnsafeExpect { + pub fn set_balance(env: Env, address: Address, balance: i128) -> State { + // Only the owner can set the balance. + address.require_auth(); + + // Get the current state. + let mut state = Self::get_state(env.clone()); + + // Set the new account to have total supply if it doesn't exist. + if !state.balances.contains_key(address.clone()) { + state.balances.set(address, balance); + // Save the state. + env.storage().persistent().set(&STATE, &state); + } + + state + } + + // Returns the balance of a given account. + pub fn balance_of(env: Env, owner: Address) -> (i128, i128) { + let state = Self::get_state(env); + + // For this example we will get the same balance twice. + let balance_1 = state.balances.get(owner.clone()); + let balance_2 = state.balances.get(owner); + if balance_1.is_none() || balance_2.is_none() { + return (0, 0); + } + ( + balance_1.expect("could not get balance"), + balance_2.expect("could not get balance"), + ) + } + + /// Return the current state. + pub fn get_state(env: Env) -> State { + env.storage().persistent().get(&STATE).unwrap_or(State { + balances: Map::new(&env), + }) + } +} + +#[cfg(test)] +const TOTAL_SUPPLY: i128 = 200; + +#[cfg(test)] +mod tests { + + use soroban_sdk::Env; + + use crate::{UnsafeExpect, UnsafeExpectClient, TOTAL_SUPPLY}; + + #[test] + fn balance_of_works() { + // Given + let env = Env::default(); + let contract_id = env.register_contract(None, UnsafeExpect); + let client = UnsafeExpectClient::new(&env, &contract_id); + + // When + client + .mock_all_auths() + .set_balance(&contract_id, &TOTAL_SUPPLY); + let balance = client.balance_of(&contract_id); + + // Then + assert_eq!(TOTAL_SUPPLY, balance.0); + assert_eq!(TOTAL_SUPPLY, balance.1); + } + + #[test] + fn balance_of_unwrap_works() { + // Given + let env = Env::default(); + let contract_id = env.register_contract(None, UnsafeExpect); + let client = UnsafeExpectClient::new(&env, &contract_id); + + // When - Balance not set + let balance = client.balance_of(&contract_id); + + // Then + assert_eq!(0, balance.0); + assert_eq!(0, balance.1); + } +} diff --git a/test-cases/unsafe-expect/unsafe-expect-4/vulnerable-example/Cargo.toml b/test-cases/unsafe-expect/unsafe-expect-4/vulnerable-example/Cargo.toml new file mode 100644 index 00000000..ee1eaf5f --- /dev/null +++ b/test-cases/unsafe-expect/unsafe-expect-4/vulnerable-example/Cargo.toml @@ -0,0 +1,30 @@ +[package] +edition = "2021" +name = "unsafe-expect-vulnerable-4" +version = "0.1.0" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +soroban-sdk = { version = "=20.0.0" } + +[dev_dependencies] +soroban-sdk = { version = "=20.0.0", features = ["testutils"] } + +[features] +testutils = ["soroban-sdk/testutils"] + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/unsafe-expect/unsafe-expect-4/vulnerable-example/src/lib.rs b/test-cases/unsafe-expect/unsafe-expect-4/vulnerable-example/src/lib.rs new file mode 100644 index 00000000..726a6e8c --- /dev/null +++ b/test-cases/unsafe-expect/unsafe-expect-4/vulnerable-example/src/lib.rs @@ -0,0 +1,91 @@ +use soroban_sdk::{contract, contractimpl, contracttype, symbol_short, Address, Env, Map, Symbol}; + +#[contract] +pub struct UnsafeExpect; + +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct State { + balances: Map, +} +const STATE: Symbol = symbol_short!("STATE"); + +#[contractimpl] +impl UnsafeExpect { + pub fn set_balance(env: Env, address: Address, balance: i128) -> State { + // Get the current state. + let mut state = Self::get_state(env.clone()); + + // Set the new account to have total supply if it doesn't exist. + if !state.balances.contains_key(address.clone()) { + state.balances.set(address, balance); + // Save the state. + env.storage().persistent().set(&STATE, &state); + } + + state + } + + // Returns the balance of a given account. + pub fn balance_of(env: Env, owner: Address) -> (i128, i128) { + let state = Self::get_state(env); + // For similarity with the remediated-example, we will return the same value twice. + ( + state + .balances + .get(owner.clone()) + .expect("could not get balance"), + state.balances.get(owner).expect("could not get balance"), + ) + } + + /// Return the current state. + pub fn get_state(env: Env) -> State { + env.storage().persistent().get(&STATE).unwrap_or(State { + balances: Map::new(&env), + }) + } +} + +#[cfg(test)] +const TOTAL_SUPPLY: i128 = 200; + +#[cfg(test)] +mod tests { + + use soroban_sdk::Env; + + use crate::{UnsafeExpect, UnsafeExpectClient, TOTAL_SUPPLY}; + + #[test] + fn balance_of_works() { + // Given + let env = Env::default(); + let contract_id = env.register_contract(None, UnsafeExpect); + let client = UnsafeExpectClient::new(&env, &contract_id); + + // When + client.set_balance(&contract_id, &TOTAL_SUPPLY); + let balances = client.balance_of(&contract_id); + + // Then + assert_eq!(TOTAL_SUPPLY, balances.0); + assert_eq!(TOTAL_SUPPLY, balances.1); + } + + #[test] + #[should_panic(expected = "could not get balance")] + fn balance_of_expect_works() { + // Given + let env = Env::default(); + let contract_id = env.register_contract(None, UnsafeExpect); + let client = UnsafeExpectClient::new(&env, &contract_id); + + // When - Balance not set + let _balance_1 = client.balance_of(&contract_id); + + // Then + + // Test should panic + } +} diff --git a/test-cases/unsafe-unwrap/Cargo.toml b/test-cases/unsafe-unwrap/Cargo.toml new file mode 100644 index 00000000..d7b45aae --- /dev/null +++ b/test-cases/unsafe-unwrap/Cargo.toml @@ -0,0 +1,21 @@ +[workspace] +exclude = [".cargo", "target"] +members = ["unsafe-unwrap-*/*"] +resolver = "2" + +[workspace.dependencies] +soroban-sdk = { version = "=20.0.0" } + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/unsafe-unwrap/unsafe-unwrap-1/remediated-example/Cargo.toml b/test-cases/unsafe-unwrap/unsafe-unwrap-1/remediated-example/Cargo.toml index 3b44681e..a33b76ee 100644 --- a/test-cases/unsafe-unwrap/unsafe-unwrap-1/remediated-example/Cargo.toml +++ b/test-cases/unsafe-unwrap/unsafe-unwrap-1/remediated-example/Cargo.toml @@ -1,30 +1,16 @@ [package] -name = "unsafe-unwrap-1-remediated" -version = "0.1.0" edition = "2021" +name = "unsafe-unwrap-remediated-1" +version = "0.1.0" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/unsafe-unwrap/unsafe-unwrap-1/vulnerable-example/Cargo.toml b/test-cases/unsafe-unwrap/unsafe-unwrap-1/vulnerable-example/Cargo.toml index 5ecabe18..42f74d39 100644 --- a/test-cases/unsafe-unwrap/unsafe-unwrap-1/vulnerable-example/Cargo.toml +++ b/test-cases/unsafe-unwrap/unsafe-unwrap-1/vulnerable-example/Cargo.toml @@ -1,30 +1,16 @@ [package] -name = "unsafe-unwrap-1-vulnerable" -version = "0.1.0" edition = "2021" +name = "unsafe-unwrap-vulnerable-1" +version = "0.1.0" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/unsafe-unwrap/unsafe-unwrap-2/remediated-example/Cargo.toml b/test-cases/unsafe-unwrap/unsafe-unwrap-2/remediated-example/Cargo.toml new file mode 100644 index 00000000..bb0d0f36 --- /dev/null +++ b/test-cases/unsafe-unwrap/unsafe-unwrap-2/remediated-example/Cargo.toml @@ -0,0 +1,16 @@ +[package] +edition = "2021" +name = "unsafe-unwrap-remediated-2" +version = "0.1.0" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +soroban-sdk = { workspace = true } + +[dev_dependencies] +soroban-sdk = { workspace = true, features = ["testutils"] } + +[features] +testutils = ["soroban-sdk/testutils"] diff --git a/test-cases/unsafe-unwrap/unsafe-unwrap-2/remediated-example/src/lib.rs b/test-cases/unsafe-unwrap/unsafe-unwrap-2/remediated-example/src/lib.rs new file mode 100644 index 00000000..102fe50a --- /dev/null +++ b/test-cases/unsafe-unwrap/unsafe-unwrap-2/remediated-example/src/lib.rs @@ -0,0 +1,59 @@ +#![no_std] +use soroban_sdk::{contract, contracterror, contractimpl}; + +#[contract] +pub struct UnsafeUnwrap; + +#[contracterror] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[repr(u32)] +pub enum Error { + CustomError = 1, +} + +#[contractimpl] +impl UnsafeUnwrap { + pub fn safe_unwrap(n: u64) -> u64 { + let result = Self::non_zero_or_error(n); + if result.is_err() { + return 0; + } + result.unwrap() + } + + pub fn non_zero_or_error(n: u64) -> Result { + if n == 0 { + return Err(Error::CustomError); + } + Ok(n) + } +} + +#[cfg(test)] +mod tests { + use crate::UnsafeUnwrap; + + #[test] + fn test_unwrap_or_zero() { + // Given + let test_value = 0; + + // When + let result = UnsafeUnwrap::safe_unwrap(test_value); + + // Then + assert_eq!(result, test_value); + } + + #[test] + fn test_unwrap_or_non_zero() { + // Given + let test_value = 100; + + // When + let result = UnsafeUnwrap::safe_unwrap(test_value); + + // Then + assert_eq!(result, test_value); + } +} diff --git a/test-cases/unsafe-unwrap/unsafe-unwrap-2/vulnerable-example/Cargo.toml b/test-cases/unsafe-unwrap/unsafe-unwrap-2/vulnerable-example/Cargo.toml new file mode 100644 index 00000000..32ba2f01 --- /dev/null +++ b/test-cases/unsafe-unwrap/unsafe-unwrap-2/vulnerable-example/Cargo.toml @@ -0,0 +1,16 @@ +[package] +edition = "2021" +name = "unsafe-unwrap-vulnerable-2" +version = "0.1.0" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +soroban-sdk = { workspace = true } + +[dev_dependencies] +soroban-sdk = { workspace = true, features = ["testutils"] } + +[features] +testutils = ["soroban-sdk/testutils"] diff --git a/test-cases/unsafe-unwrap/unsafe-unwrap-2/vulnerable-example/src/lib.rs b/test-cases/unsafe-unwrap/unsafe-unwrap-2/vulnerable-example/src/lib.rs new file mode 100644 index 00000000..83dd2a2f --- /dev/null +++ b/test-cases/unsafe-unwrap/unsafe-unwrap-2/vulnerable-example/src/lib.rs @@ -0,0 +1,57 @@ +#![no_std] +use soroban_sdk::{contract, contracterror, contractimpl}; + +#[contract] +pub struct UnsafeUnwrap; + +#[contracterror] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[repr(u32)] +pub enum Error { + CustomError = 1, +} + +#[contractimpl] +impl UnsafeUnwrap { + pub fn unwrap(n: u64) -> u64 { + let result = Self::non_zero_or_error(n); + result.unwrap() + } + + pub fn non_zero_or_error(n: u64) -> Result { + if n == 0 { + return Err(Error::CustomError); + } + Ok(n) + } +} + +#[cfg(test)] +mod tests { + use crate::UnsafeUnwrap; + + #[test] + #[should_panic(expected = "called `Result::unwrap()` on an `Err` value: CustomError")] + fn test_unwrap_or_zero() { + // Given + let test_value = 0; + + // When + let _result = UnsafeUnwrap::unwrap(test_value); + + // Then + // The test should panic + } + + #[test] + fn test_unwrap_or_non_zero() { + // Given + let test_value = 100; + + // When + let result = UnsafeUnwrap::unwrap(100); + + // Then + assert_eq!(result, test_value); + } +} diff --git a/test-cases/unsafe-unwrap/unsafe-unwrap-3/remediated-example/Cargo.toml b/test-cases/unsafe-unwrap/unsafe-unwrap-3/remediated-example/Cargo.toml new file mode 100644 index 00000000..52be41f1 --- /dev/null +++ b/test-cases/unsafe-unwrap/unsafe-unwrap-3/remediated-example/Cargo.toml @@ -0,0 +1,16 @@ +[package] +edition = "2021" +name = "unsafe-unwrap-remediated-3" +version = "0.1.0" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +soroban-sdk = { workspace = true } + +[dev_dependencies] +soroban-sdk = { workspace = true, features = ["testutils"] } + +[features] +testutils = ["soroban-sdk/testutils"] diff --git a/test-cases/unsafe-unwrap/unsafe-unwrap-3/remediated-example/src/lib.rs b/test-cases/unsafe-unwrap/unsafe-unwrap-3/remediated-example/src/lib.rs new file mode 100644 index 00000000..c4a26c6f --- /dev/null +++ b/test-cases/unsafe-unwrap/unsafe-unwrap-3/remediated-example/src/lib.rs @@ -0,0 +1,60 @@ +#![no_std] +use soroban_sdk::{contract, contracterror, contractimpl}; + +#[contract] +pub struct UnsafeUnwrap; + +#[contracterror] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[repr(u32)] +pub enum Error { + CustomError = 1, +} + +#[contractimpl] +impl UnsafeUnwrap { + pub fn safe_unwrap(n: u64) -> u64 { + let result = Self::non_zero_or_error(n); + let mut return_value = 0; + if result.is_ok() { + return_value = result.unwrap(); + } + return_value + } + + pub fn non_zero_or_error(n: u64) -> Result { + if n == 0 { + return Err(Error::CustomError); + } + Ok(n) + } +} + +#[cfg(test)] +mod tests { + use crate::UnsafeUnwrap; + + #[test] + fn test_unwrap_or_zero() { + // Given + let test_value = 0; + + // When + let result = UnsafeUnwrap::safe_unwrap(test_value); + + // Then + assert_eq!(result, test_value); + } + + #[test] + fn test_unwrap_or_non_zero() { + // Given + let test_value = 100; + + // When + let result = UnsafeUnwrap::safe_unwrap(test_value); + + // Then + assert_eq!(result, test_value); + } +} diff --git a/test-cases/unsafe-unwrap/unsafe-unwrap-3/vulnerable-example/Cargo.toml b/test-cases/unsafe-unwrap/unsafe-unwrap-3/vulnerable-example/Cargo.toml new file mode 100644 index 00000000..6570b63c --- /dev/null +++ b/test-cases/unsafe-unwrap/unsafe-unwrap-3/vulnerable-example/Cargo.toml @@ -0,0 +1,16 @@ +[package] +edition = "2021" +name = "unsafe-unwrap-vulnerable-3" +version = "0.1.0" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +soroban-sdk = { workspace = true } + +[dev_dependencies] +soroban-sdk = { workspace = true, features = ["testutils"] } + +[features] +testutils = ["soroban-sdk/testutils"] diff --git a/test-cases/unsafe-unwrap/unsafe-unwrap-3/vulnerable-example/src/lib.rs b/test-cases/unsafe-unwrap/unsafe-unwrap-3/vulnerable-example/src/lib.rs new file mode 100644 index 00000000..83dd2a2f --- /dev/null +++ b/test-cases/unsafe-unwrap/unsafe-unwrap-3/vulnerable-example/src/lib.rs @@ -0,0 +1,57 @@ +#![no_std] +use soroban_sdk::{contract, contracterror, contractimpl}; + +#[contract] +pub struct UnsafeUnwrap; + +#[contracterror] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[repr(u32)] +pub enum Error { + CustomError = 1, +} + +#[contractimpl] +impl UnsafeUnwrap { + pub fn unwrap(n: u64) -> u64 { + let result = Self::non_zero_or_error(n); + result.unwrap() + } + + pub fn non_zero_or_error(n: u64) -> Result { + if n == 0 { + return Err(Error::CustomError); + } + Ok(n) + } +} + +#[cfg(test)] +mod tests { + use crate::UnsafeUnwrap; + + #[test] + #[should_panic(expected = "called `Result::unwrap()` on an `Err` value: CustomError")] + fn test_unwrap_or_zero() { + // Given + let test_value = 0; + + // When + let _result = UnsafeUnwrap::unwrap(test_value); + + // Then + // The test should panic + } + + #[test] + fn test_unwrap_or_non_zero() { + // Given + let test_value = 100; + + // When + let result = UnsafeUnwrap::unwrap(100); + + // Then + assert_eq!(result, test_value); + } +} diff --git a/test-cases/unsafe-unwrap/unsafe-unwrap-4/remediated-example/Cargo.toml b/test-cases/unsafe-unwrap/unsafe-unwrap-4/remediated-example/Cargo.toml new file mode 100644 index 00000000..f583d6b1 --- /dev/null +++ b/test-cases/unsafe-unwrap/unsafe-unwrap-4/remediated-example/Cargo.toml @@ -0,0 +1,16 @@ +[package] +edition = "2021" +name = "unsafe-unwrap-remediated-4" +version = "0.1.0" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +soroban-sdk = { workspace = true } + +[dev_dependencies] +soroban-sdk = { workspace = true, features = ["testutils"] } + +[features] +testutils = ["soroban-sdk/testutils"] diff --git a/test-cases/unsafe-unwrap/unsafe-unwrap-4/remediated-example/src/lib.rs b/test-cases/unsafe-unwrap/unsafe-unwrap-4/remediated-example/src/lib.rs new file mode 100644 index 00000000..b457299a --- /dev/null +++ b/test-cases/unsafe-unwrap/unsafe-unwrap-4/remediated-example/src/lib.rs @@ -0,0 +1,63 @@ +#![no_std] +use soroban_sdk::{contract, contracterror, contractimpl}; + +#[contract] +pub struct UnsafeUnwrap; + +#[contracterror] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[repr(u32)] +pub enum Error { + CustomError = 1, +} + +#[contractimpl] +impl UnsafeUnwrap { + pub fn safe_unwrap(n: u64) -> (u64, u64) { + // We get the same element twice for demonstration purposes + let result_1 = Self::non_zero_or_error(n); + let result_2 = Self::non_zero_or_error(n); + if result_1.is_err() || result_2.is_err() { + return (0, 0); + } + (result_1.unwrap(), result_2.unwrap()) + } + + pub fn non_zero_or_error(n: u64) -> Result { + if n == 0 { + return Err(Error::CustomError); + } + Ok(n) + } +} + +#[cfg(test)] +mod tests { + use crate::UnsafeUnwrap; + + #[test] + fn test_unwrap_or_zero() { + // Given + let test_value = 0; + + // When + let result = UnsafeUnwrap::safe_unwrap(test_value); + + // Then + assert_eq!(result.0, test_value); + assert_eq!(result.1, test_value); + } + + #[test] + fn test_unwrap_or_non_zero() { + // Given + let test_value = 100; + + // When + let result = UnsafeUnwrap::safe_unwrap(test_value); + + // Then + assert_eq!(result.0, test_value); + assert_eq!(result.1, test_value); + } +} diff --git a/test-cases/unsafe-unwrap/unsafe-unwrap-4/vulnerable-example/Cargo.toml b/test-cases/unsafe-unwrap/unsafe-unwrap-4/vulnerable-example/Cargo.toml new file mode 100644 index 00000000..06bbb0c3 --- /dev/null +++ b/test-cases/unsafe-unwrap/unsafe-unwrap-4/vulnerable-example/Cargo.toml @@ -0,0 +1,16 @@ +[package] +edition = "2021" +name = "unsafe-unwrap-vulnerable-4" +version = "0.1.0" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +soroban-sdk = { workspace = true } + +[dev_dependencies] +soroban-sdk = { workspace = true, features = ["testutils"] } + +[features] +testutils = ["soroban-sdk/testutils"] diff --git a/test-cases/unsafe-unwrap/unsafe-unwrap-4/vulnerable-example/src/lib.rs b/test-cases/unsafe-unwrap/unsafe-unwrap-4/vulnerable-example/src/lib.rs new file mode 100644 index 00000000..8c84c1fd --- /dev/null +++ b/test-cases/unsafe-unwrap/unsafe-unwrap-4/vulnerable-example/src/lib.rs @@ -0,0 +1,58 @@ +#![no_std] +use soroban_sdk::{contract, contracterror, contractimpl}; + +#[contract] +pub struct UnsafeUnwrap; + +#[contracterror] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[repr(u32)] +pub enum Error { + CustomError = 1, +} + +#[contractimpl] +impl UnsafeUnwrap { + pub fn unwrap(n: u64) -> (u64, u64) { + let result = Self::non_zero_or_error(n); + (result.unwrap(), result.unwrap()) + } + + pub fn non_zero_or_error(n: u64) -> Result { + if n == 0 { + return Err(Error::CustomError); + } + Ok(n) + } +} + +#[cfg(test)] +mod tests { + use crate::UnsafeUnwrap; + + #[test] + #[should_panic(expected = "called `Result::unwrap()` on an `Err` value: CustomError")] + fn test_unwrap_or_zero() { + // Given + let test_value = 0; + + // When + let _result = UnsafeUnwrap::unwrap(test_value); + + // Then + // The test should panic + } + + #[test] + fn test_unwrap_or_non_zero() { + // Given + let test_value = 100; + + // When + let result = UnsafeUnwrap::unwrap(100); + + // Then + assert_eq!(result.0, test_value); + assert_eq!(result.1, test_value); + } +} diff --git a/test-cases/unused-return-enum/Cargo.toml b/test-cases/unused-return-enum/Cargo.toml new file mode 100644 index 00000000..f5202497 --- /dev/null +++ b/test-cases/unused-return-enum/Cargo.toml @@ -0,0 +1,21 @@ +[workspace] +exclude = [".cargo", "target"] +members = ["unused-return-enum-*/*"] +resolver = "2" + +[workspace.dependencies] +soroban-sdk = { version = "=20.0.0" } + +[profile.release] +codegen-units = 1 +debug = 0 +debug-assertions = false +lto = true +opt-level = "z" +overflow-checks = true +panic = "abort" +strip = "symbols" + +[profile.release-with-logs] +debug-assertions = true +inherits = "release" diff --git a/test-cases/unused-return-enum/unused-return-enum-1/remediated-example/Cargo.toml b/test-cases/unused-return-enum/unused-return-enum-1/remediated-example/Cargo.toml index 75e353f4..80a5dec2 100644 --- a/test-cases/unused-return-enum/unused-return-enum-1/remediated-example/Cargo.toml +++ b/test-cases/unused-return-enum/unused-return-enum-1/remediated-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "unused-return-enum-remediated-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/unused-return-enum/unused-return-enum-1/vulnerable-example/Cargo.toml b/test-cases/unused-return-enum/unused-return-enum-1/vulnerable-example/Cargo.toml index c90fa4dc..529f902f 100644 --- a/test-cases/unused-return-enum/unused-return-enum-1/vulnerable-example/Cargo.toml +++ b/test-cases/unused-return-enum/unused-return-enum-1/vulnerable-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "unused-return-enum-vulnerable-1" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/unused-return-enum/unused-return-enum-2/remediated-example/Cargo.toml b/test-cases/unused-return-enum/unused-return-enum-2/remediated-example/Cargo.toml index 1edbef17..01337627 100644 --- a/test-cases/unused-return-enum/unused-return-enum-2/remediated-example/Cargo.toml +++ b/test-cases/unused-return-enum/unused-return-enum-2/remediated-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "unused-return-enum-remediated-2" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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 diff --git a/test-cases/unused-return-enum/unused-return-enum-2/vulnerable-example/Cargo.toml b/test-cases/unused-return-enum/unused-return-enum-2/vulnerable-example/Cargo.toml index aed3d0cc..d0496327 100644 --- a/test-cases/unused-return-enum/unused-return-enum-2/vulnerable-example/Cargo.toml +++ b/test-cases/unused-return-enum/unused-return-enum-2/vulnerable-example/Cargo.toml @@ -1,30 +1,16 @@ [package] +edition = "2021" name = "unused-return-enum-vulnerable-2" version = "0.1.0" -edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=20.0.0" } +soroban-sdk = { workspace = true } [dev_dependencies] -soroban-sdk = { version = "=20.0.0", features = ["testutils"] } +soroban-sdk = { workspace = true, 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