diff --git a/toolchains/solidity/linter/core/solidhunter-lib/src/rules/security/avoid_tx_origin.rs b/toolchains/solidity/linter/core/solidhunter-lib/src/rules/security/avoid_tx_origin.rs new file mode 100644 index 00000000..aded88ab --- /dev/null +++ b/toolchains/solidity/linter/core/solidhunter-lib/src/rules/security/avoid_tx_origin.rs @@ -0,0 +1,95 @@ +use crate::linter::SolidFile; +use crate::rules::types::*; +use crate::types::*; +use ast_extractor::*; + +pub const RULE_ID: &str = "avoid-tx-origin"; +const MESSAGE: &str = "Avoid to use tx.origin"; + +struct ExprVisitor { + exprs: Vec, +} + +impl ExprVisitor { + pub fn new() -> Self { + Self { + exprs: Vec::new(), + } + } +} + +impl<'ast> Visit<'ast> for ExprVisitor { + fn visit_expr_member(&mut self,i: &'ast ExprMember) { + self.exprs.push(i.clone()); + visit::visit_expr_member(self, i); + } +} + +pub struct AvoidTxOrigin { + data: RuleEntry, +} + +impl AvoidTxOrigin { + fn create_diag( + &self, + location: (LineColumn, LineColumn), + file: &SolidFile, + ) -> LintDiag { + LintDiag { + id: RULE_ID.to_string(), + range: Range { + start: Position { + line: location.0.line, + character: location.0.column, + }, + end: Position { + line: location.1.line, + character: location.1.column, + }, + }, + message: MESSAGE.to_string(), + severity: Some(self.data.severity), + code: None, + source: None, + uri: file.path.clone(), + source_file_content: file.content.clone(), + } + } +} + +impl RuleType for AvoidTxOrigin { + fn diagnose(&self, file: &SolidFile, _files: &[SolidFile]) -> Vec { + let mut res = Vec::new(); + let mut visitor = ExprVisitor::new(); + for contract in ast_extractor::retriever::retrieve_contract_nodes(&file.data) { + visitor.visit_item_contract(&contract); + } + + for expr in visitor.exprs { + if let Expr::Ident(ident) = &*expr.expr { + if let Expr::Ident(ident2) = &*expr.member { + if ident == "tx" && ident2 == "origin" { + let location = (expr.span().start(), expr.span().end()); + res.push(self.create_diag(location, file)); + } + } + } + } + res + } +} + +impl AvoidTxOrigin { + pub(crate) fn create(data: RuleEntry) -> Box { + let rule = AvoidTxOrigin { data }; + Box::new(rule) + } + + pub(crate) fn create_default() -> RuleEntry { + RuleEntry { + id: RULE_ID.to_string(), + severity: Severity::WARNING, + data: vec![], + } + } +} diff --git a/toolchains/solidity/linter/core/solidhunter-lib/testdata/AvoidTxOrigin/.solidhunter.json b/toolchains/solidity/linter/core/solidhunter-lib/testdata/AvoidTxOrigin/.solidhunter.json new file mode 100644 index 00000000..0ab201ac --- /dev/null +++ b/toolchains/solidity/linter/core/solidhunter-lib/testdata/AvoidTxOrigin/.solidhunter.json @@ -0,0 +1,12 @@ +{ + "name": "solidhunter", + "includes": [], + "plugins": [], + "rules": [ + { + "id": "avoid-tx-origin", + "severity": "WARNING", + "data": [] + } + ] +} \ No newline at end of file diff --git a/toolchains/solidity/linter/core/solidhunter-lib/testdata/AvoidTxOrigin/file.sol b/toolchains/solidity/linter/core/solidhunter-lib/testdata/AvoidTxOrigin/file.sol new file mode 100644 index 00000000..97291c3b --- /dev/null +++ b/toolchains/solidity/linter/core/solidhunter-lib/testdata/AvoidTxOrigin/file.sol @@ -0,0 +1,10 @@ +pragma solidity 0.8.0; + +contract Test { + function awesome() public returns (address) { + return tx.origin; + } + function notAwesome() public returns (address) { + return msg.sender; + } +} \ No newline at end of file diff --git a/toolchains/solidity/linter/core/solidhunter-lib/testdata/AvoidTxOrigin/findings.csv b/toolchains/solidity/linter/core/solidhunter-lib/testdata/AvoidTxOrigin/findings.csv new file mode 100644 index 00000000..0d8c8b8c --- /dev/null +++ b/toolchains/solidity/linter/core/solidhunter-lib/testdata/AvoidTxOrigin/findings.csv @@ -0,0 +1 @@ +avoid-tx-origin:5:15:5:24 \ No newline at end of file