Skip to content

Commit

Permalink
Try fix detector
Browse files Browse the repository at this point in the history
  • Loading branch information
jgcrosta committed Nov 6, 2024
1 parent 62ee9ef commit 7d20545
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 50 deletions.
63 changes: 23 additions & 40 deletions detectors/token-interface-inference/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,31 @@

extern crate rustc_errors;
extern crate rustc_hir;
extern crate rustc_middle;
extern crate rustc_span;

use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::diagnostics::span_lint;
use edit_distance::edit_distance;
use rustc_hir::{intravisit::Visitor, Node};
use rustc_lint::{LateContext, LateLintPass};

use if_chain::if_chain;
use rustc_errors::MultiSpan;
use rustc_span::Span;

use std::collections::HashSet;
use std::vec;
use rustc_hir::{intravisit::FnKind, Body, FnDecl, Item, ItemKind, Node};
use rustc_lint::{LateContext, LateLintPass};
use rustc_span::{def_id::DefId, def_id::LocalDefId, Span};
use std::{
collections::HashMap,
collections::HashSet,
ops::{Div, Mul},
vec,
};
use utils::FunctionCallVisitor;

use rustc_span::def_id::DefId;

const LINT_MESSAGE: &str =
"This contract seems like a Token, consider implementing the Token Interface trait";
const CANONICAL_FUNCTIONS_AMOUNT: u16 = 10;
const INCLUDED_FUNCTIONS_THRESHOLD: u16 = 60;
const TOKEN_INTERFACE_PATH: &str = "soroban_sdk::token::TokenInterface";

dylint_linting::impl_late_lint! {
pub TOKEN_INTERFACE_INFERENCE,
Warn,
"",
LINT_MESSAGE,
TokenInterfaceInference::default(),
{
name: "Token Interface Implementation Analyzer",
Expand All @@ -44,24 +39,21 @@ dylint_linting::impl_late_lint! {

#[derive(Default)]
struct TokenInterfaceInference {
function_call_graph: HashMap<DefId, HashSet<DefId>>,
checked_functions: HashSet<String>,
canonical_funcs_def_id: HashSet<DefId>,
impl_token_interface_trait: bool,
detected_canonical_functions_count: u16,
funcs_spans: Vec<Span>,
}

impl<'tcx> LateLintPass<'tcx> for TokenInterfaceInference {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx rustc_hir::Item<'tcx>) {
if let rustc_hir::ItemKind::Impl(impl_block) = item.kind {
if let Some(trait_ref) = impl_block.of_trait {
let trait_def_id = trait_ref.path.res.def_id();
let trait_name = cx.tcx.def_path_str(trait_def_id);

if trait_name == "soroban_sdk::token::TokenInterface" {
self.impl_token_interface_trait = true;
}
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
if_chain! {
if let ItemKind::Impl(impl_block) = item.kind;
if let Some(trait_ref) = impl_block.of_trait;
if let Some(trait_def_id) = trait_ref.path.res.opt_def_id();
if cx.tcx.def_path_str(trait_def_id) == TOKEN_INTERFACE_PATH;
then {
self.impl_token_interface_trait = true;
}
}
}
Expand All @@ -78,35 +70,30 @@ impl<'tcx> LateLintPass<'tcx> for TokenInterfaceInference {
.div(CANONICAL_FUNCTIONS_AMOUNT)
>= INCLUDED_FUNCTIONS_THRESHOLD
{
span_lint_and_help(
span_lint(
cx,
TOKEN_INTERFACE_INFERENCE,
MultiSpan::from_spans(self.funcs_spans.clone()),
LINT_MESSAGE,
None,
"",
);
}
}

fn check_fn(
&mut self,
cx: &LateContext<'tcx>,
_: rustc_hir::intravisit::FnKind<'tcx>,
_fn_decl: &'tcx rustc_hir::FnDecl<'tcx>,
body: &'tcx rustc_hir::Body<'tcx>,
_: FnKind<'tcx>,
_: &'tcx FnDecl<'tcx>,
_: &'tcx Body<'tcx>,
span: Span,
local_def_id: rustc_span::def_id::LocalDefId,
local_def_id: LocalDefId,
) {
let def_id = local_def_id.to_def_id();
self.checked_functions.insert(cx.tcx.def_path_str(def_id));

if span.from_expansion() {
return;
}

let def_id = local_def_id.to_def_id();
let fn_name = cx.tcx.def_path_str(def_id);

let fn_name_span = if let Some(node) = cx.tcx.hir().get_if_local(def_id) {
match node {
Node::Item(item) => Some(item.ident.span),
Expand All @@ -117,10 +104,6 @@ impl<'tcx> LateLintPass<'tcx> for TokenInterfaceInference {
None
};

let mut function_call_visitor =
FunctionCallVisitor::new(cx, def_id, &mut self.function_call_graph);
function_call_visitor.visit_body(body);

// If the function is part of the token interface, I store its defid.
if verify_token_interface_function_similarity(fn_name.clone()) {
self.detected_canonical_functions_count += 1;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
edition = "2021"
name = "token-interface-inference-remediated-1"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]
Expand All @@ -10,9 +10,5 @@ crate-type = ["cdylib"]
soroban-sdk = { workspace = true }
soroban-token-sdk = { workspace = true }

[dev_dependencies]
soroban-sdk = { workspace = true, features = ["testutils"] }
soroban-token-sdk = { workspace = true }

[features]
testutils = ["soroban-sdk/testutils"]
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
edition = "2021"
name = "token-interface-inference-vulnerable-1"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]
Expand All @@ -10,9 +10,5 @@ crate-type = ["cdylib"]
soroban-sdk = { workspace = true }
soroban-token-sdk = { workspace = true }

[dev_dependencies]
soroban-sdk = { workspace = true, features = ["testutils"] }
soroban-token-sdk = { workspace = true }

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

0 comments on commit 7d20545

Please sign in to comment.