Skip to content

Commit

Permalink
Merge pull request #374 from CoinFabrik/ci-cd-fixup
Browse files Browse the repository at this point in the history
CI/CD fixup
  • Loading branch information
Helios-vmg authored Nov 5, 2024
2 parents 558e079 + 57826b0 commit 1200958
Show file tree
Hide file tree
Showing 22 changed files with 138 additions and 82 deletions.
12 changes: 6 additions & 6 deletions detectors/dos-unexpected-revert-with-vector/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ use rustc_span::Span;
const LINT_MESSAGE: &str = "This vector operation is called without access control";

dylint_linting::impl_late_lint! {
pub UNEXPECTED_REVERT_WARN,
pub DOS_UNEXPECTED_REVERT_WITH_VECTOR,
Warn,
"",
UnexpectedRevertWarn::default(),
DosUnexpectedRevertWithVector::default(),
{
name: "Unexpected Revert Inserting to Storage",
long_message: " It occurs by preventing transactions by other users from being successfully executed forcing the blockchain state to revert to its original state.",
Expand All @@ -32,14 +32,14 @@ dylint_linting::impl_late_lint! {
}

#[derive(Default)]
pub struct UnexpectedRevertWarn {}
impl UnexpectedRevertWarn {
pub struct DosUnexpectedRevertWithVector {}
impl DosUnexpectedRevertWithVector {
pub fn new() -> Self {
Self {}
}
}

impl<'tcx> LateLintPass<'tcx> for UnexpectedRevertWarn {
impl<'tcx> LateLintPass<'tcx> for DosUnexpectedRevertWithVector {
fn check_fn(
&mut self,
cx: &LateContext<'tcx>,
Expand Down Expand Up @@ -87,7 +87,7 @@ impl<'tcx> LateLintPass<'tcx> for UnexpectedRevertWarn {
if uvf_storage.push_def_id.is_some() && !uvf_storage.require_auth {
span_lint(
uvf_storage.cx,
UNEXPECTED_REVERT_WARN,
DOS_UNEXPECTED_REVERT_WITH_VECTOR,
uvf_storage.push_span.unwrap(),
LINT_MESSAGE,
);
Expand Down
20 changes: 10 additions & 10 deletions detectors/integer-overflow-or-underflow/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use utils::ConstantAnalyzer;
pub const LINT_MESSAGE: &str = "Potential for integer arithmetic overflow/underflow. Consider checked, wrapping or saturating arithmetic.";

dylint_linting::declare_late_lint! {
pub INTEGER_OVERFLOW_UNDERFLOW,
pub INTEGER_OVERFLOW_OR_UNDERFLOW,
Warn,
LINT_MESSAGE,
{
Expand All @@ -30,15 +30,15 @@ dylint_linting::declare_late_lint! {
enum Type {
Overflow,
Underflow,
OverflowUnderflow,
OverflowAndUnderflow,
}

impl Type {
fn message(&self) -> &'static str {
match self {
Type::Overflow => "overflow",
Type::Underflow => "underflow",
Type::OverflowUnderflow => "overflow or underflow",
Type::OverflowAndUnderflow => "overflow or underflow",
}
}
}
Expand Down Expand Up @@ -84,14 +84,14 @@ impl Finding {
)
}
}
pub struct IntegerOverflowUnderflowVisitor<'a, 'tcx> {
pub struct IntegerOverflowOrUnderflowVisitor<'a, 'tcx> {
cx: &'a LateContext<'tcx>,
findings: Vec<Finding>,
is_complex_operation: bool,
constant_analyzer: ConstantAnalyzer<'a, 'tcx>,
}

impl<'tcx> IntegerOverflowUnderflowVisitor<'_, 'tcx> {
impl<'tcx> IntegerOverflowOrUnderflowVisitor<'_, 'tcx> {
pub fn check_pow(&mut self, expr: &Expr<'tcx>, base: &Expr<'tcx>, exponent: &Expr<'tcx>) {
if self.constant_analyzer.is_constant(base) && self.constant_analyzer.is_constant(exponent)
{
Expand Down Expand Up @@ -137,7 +137,7 @@ impl<'tcx> IntegerOverflowUnderflowVisitor<'_, 'tcx> {
}

let (finding_type, cause) = if self.is_complex_operation {
(Type::OverflowUnderflow, Cause::Multiple)
(Type::OverflowAndUnderflow, Cause::Multiple)
} else {
match op {
BinOpKind::Add => (Type::Overflow, Cause::Add),
Expand All @@ -152,7 +152,7 @@ impl<'tcx> IntegerOverflowUnderflowVisitor<'_, 'tcx> {
}
}

impl<'a, 'tcx> Visitor<'tcx> for IntegerOverflowUnderflowVisitor<'a, 'tcx> {
impl<'a, 'tcx> Visitor<'tcx> for IntegerOverflowOrUnderflowVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
match expr.kind {
ExprKind::Binary(op, lhs, rhs) | ExprKind::AssignOp(op, lhs, rhs) => {
Expand All @@ -178,7 +178,7 @@ impl<'a, 'tcx> Visitor<'tcx> for IntegerOverflowUnderflowVisitor<'a, 'tcx> {
}
}

impl<'tcx> LateLintPass<'tcx> for IntegerOverflowUnderflow {
impl<'tcx> LateLintPass<'tcx> for IntegerOverflowOrUnderflow {
fn check_fn(
&mut self,
cx: &LateContext<'tcx>,
Expand All @@ -201,7 +201,7 @@ impl<'tcx> LateLintPass<'tcx> for IntegerOverflowUnderflow {
constant_analyzer.visit_body(body);

// Analyze the function for integer overflow/underflow
let mut visitor = IntegerOverflowUnderflowVisitor {
let mut visitor = IntegerOverflowOrUnderflowVisitor {
cx,
findings: Vec::new(),
is_complex_operation: false,
Expand All @@ -213,7 +213,7 @@ impl<'tcx> LateLintPass<'tcx> for IntegerOverflowUnderflow {
for finding in visitor.findings {
span_lint_and_help(
cx,
INTEGER_OVERFLOW_UNDERFLOW,
INTEGER_OVERFLOW_OR_UNDERFLOW,
finding.span,
finding.generate_message(),
None,
Expand Down
6 changes: 3 additions & 3 deletions detectors/iterators-over-indexing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const LINT_MESSAGE: &str =
"Hardcoding an index could lead to panic if the top bound is out of bounds.";

dylint_linting::declare_late_lint! {
pub ITERATOR_OVER_INDEXING,
pub ITERATORS_OVER_INDEXING,
Warn,
LINT_MESSAGE,
{
Expand Down Expand Up @@ -365,7 +365,7 @@ impl<'a, 'b> Visitor<'a> for ForLoopVisitor<'a, 'b> {
}
}

impl<'tcx> LateLintPass<'tcx> for IteratorOverIndexing {
impl<'tcx> LateLintPass<'tcx> for IteratorsOverIndexing {
fn check_fn(
&mut self,
cx: &rustc_lint::LateContext<'tcx>,
Expand All @@ -388,7 +388,7 @@ impl<'tcx> LateLintPass<'tcx> for IteratorOverIndexing {
for span in span_constant {
span_lint_and_help(
cx,
ITERATOR_OVER_INDEXING,
ITERATORS_OVER_INDEXING,
span,
LINT_MESSAGE,
None,
Expand Down
3 changes: 3 additions & 0 deletions run-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh
#This script is here for convenience only. Do not use it in CI/CD.
python3 scripts/run-tests2.py
88 changes: 64 additions & 24 deletions scripts/run-tests.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import os
import argparse
import time
import tempfile
import json

from utils import (
parse_json_from_string,
Expand All @@ -14,7 +16,6 @@
GREEN = "\033[92m"
ENDC = "\033[0m"


def run_tests(detector):
errors = []
directory = os.path.join("test-cases", detector)
Expand All @@ -27,28 +28,31 @@ def run_tests(detector):
if is_rust_project(root):
if run_unit_tests(root):
errors.append(root)
if run_integration_tests(detector, root):
if not run_integration_tests(detector, root):
errors.append(root)
return errors

def convert_code(s):
return s.replace('_', '-')

def run_unit_tests(root):
start_time = time.time()
returncode, _, stderr = run_subprocess(["cargo", "test", "--all-features"], root)
returncode, stdout, _ = run_subprocess(["cargo", "test", "--all-features"], root)
print_results(
returncode,
stderr,
stdout,
"unit-test",
root,
time.time() - start_time,
)
return returncode != 0



def run_integration_tests(detector, root):
start_time = time.time()

detectors_path = os.path.join(os.getcwd(), "detectors")
local_detectors = os.path.join(os.getcwd(), "detectors")

returncode, stdout, _ = run_subprocess(
[
Expand All @@ -58,12 +62,11 @@ def run_integration_tests(detector, root):
detector,
"--metadata",
"--local-detectors",
detectors_path,
local_detectors,
],
root,
)

#print("stderr: ", stderr.read())
if stdout is None:
print(
f"{RED}Failed to run integration tests in {root} - Metadata returned empty.{ENDC}"
Expand All @@ -73,36 +76,73 @@ def run_integration_tests(detector, root):
detector_metadata = parse_json_from_string(stdout)

if not isinstance(detector_metadata, dict):
print("Failed to extract JSON:\n", detector_metadata)
print("Failed to extract JSON:", detector_metadata)
return True

detector_key = detector.replace("-", "_")
short_message = detector_metadata.get(detector_key, {}).get("short_message")

returncode, stdout, stderr = run_subprocess(
[
"cargo",
"scout-audit",
"--filter",
detector,
"--local-detectors",
os.path.join(os.getcwd(), "detectors"),
],
root,
)
_, tempPath = tempfile.mkstemp(None, f'scout_{os.getpid()}_')

returncode = None
stderr = None

if detector != "unnecessary-lint-allow":
returncode, _, stderr = run_subprocess(
[
"cargo",
"scout-audit",
"--filter",
detector,
"--local-detectors",
local_detectors,
"--output-format",
"raw-json",
"--output-path",
tempPath,
],
root,
)
else:
#We need to handle this case differently, because using filter will
#cause other detectors to not run, making the test case invalid.
returncode, _, stderr = run_subprocess(
[
"cargo",
"scout-audit",
"--local-detectors",
local_detectors,
"--output-format",
"raw-json",
"--output-path",
tempPath,
],
root,
)

should_lint = root.endswith("vulnerable-example")
if should_lint and short_message and short_message not in stdout:
returncode = 1
if returncode != 0:
print(f"{RED}Scout failed to run.{ENDC}")
return False

should_fail = "vulnerable" in root
did_fail = False

with open(tempPath) as file:
detectors_triggered = {convert_code(json.loads(line.rstrip())['code']['code']) for line in file}
did_fail = detector in detectors_triggered
if should_fail != did_fail:
explanation = "it failed when it shouldn't have" if did_fail else "it didn't fail when it should have"
print(f"{RED}Test case {root} didn't pass because {explanation}.{ENDC}")
return False

print_results(
returncode,
stdout,
stderr,
"integration-test",
root,
time.time() - start_time,
)
return returncode != 0
return True


if __name__ == "__main__":
Expand Down
10 changes: 10 additions & 0 deletions scripts/run-tests2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#This script is here for convenience only. Do not use it in CI/CD.
import os
import stat

def is_dir(path):
return stat.S_ISDIR(os.stat(path).st_mode)

for name in os.listdir('test-cases'):
if is_dir('test-cases/' + name) and name[0:1] != '.' and name != 'target':
os.system(f'python3 scripts/run-tests.py --detector={name}')
2 changes: 1 addition & 1 deletion test-cases/assert-violation/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ members = ["assert-violation-*/*"]
resolver = "2"

[workspace.dependencies]
soroban-sdk = { version = "=21.4.0" }
soroban-sdk = { version = "=21.7.6" }

[profile.release]
codegen-units = 1
Expand Down
2 changes: 1 addition & 1 deletion test-cases/avoid-panic-error/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ members = ["avoid-panic-error-*/*"]
resolver = "2"

[workspace.dependencies]
soroban-sdk = { version = "=21.4.0" }
soroban-sdk = { version = "=21.7.6" }

[profile.release]
codegen-units = 1
Expand Down
3 changes: 2 additions & 1 deletion test-cases/front-running/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ members = ["front-running-*/*"]
resolver = "2"

[workspace.dependencies]
soroban-sdk = { version = "=20.0.0" }
soroban-sdk = { version = "=21.7.6" }
soroban-token-sdk = { version = "=21.7.6" }

[profile.release]
codegen-units = 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ version = "0.1.0"
crate-type = ["cdylib"]

[dependencies]
soroban-sdk = { version = "20.0.0" }
soroban-token-sdk = { version = "20.0.0" }
soroban-sdk = { workspace = true }
soroban-token-sdk = { workspace = true }

[dev-dependencies]
soroban-sdk = { version = "20.0.0", features = ["testutils"] }
soroban-sdk = { workspace = true, features = ["testutils"] }

[features]
testutils = ["soroban-sdk/testutils"]
Loading

0 comments on commit 1200958

Please sign in to comment.