Skip to content

Commit

Permalink
Sort the functions in topological order from callers to callees
Browse files Browse the repository at this point in the history
  • Loading branch information
Vara Prasad Bandaru committed Feb 8, 2024
1 parent 236b611 commit 75b9c81
Showing 1 changed file with 50 additions and 50 deletions.
100 changes: 50 additions & 50 deletions lints/missing_owner_check/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,24 +181,6 @@ fn is_safe_to_account_info<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>)
}
}

/// if `expr` is a method call of `def_path` return the receiver else None
fn is_expr_method_call<'tcx>(
cx: &LateContext<'tcx>,
expr: &Expr<'tcx>,
def_path: &[&str],
) -> Option<&'tcx Expr<'tcx>> {
if_chain! {
if let ExprKind::MethodCall(_, recv, _, _) = expr.kind;
if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
if match_def_path(cx, def_id, def_path);
then {
Some(recv)
} else {
None
}
}
}

fn contains_owner_use<'tcx>(
cx: &LateContext<'tcx>,
body: &'tcx Body<'tcx>,
Expand All @@ -209,19 +191,26 @@ fn contains_owner_use<'tcx>(
})
}

/// Checks if `expr` is references `field` on `account_expr`
fn uses_given_field<'tcx>(
fn contains_key_check<'tcx>(
cx: &LateContext<'tcx>,
body: &'tcx Body<'tcx>,
account_expr: &Expr<'tcx>,
) -> bool {
visit_expr_no_bodies(body.value, |expr| compares_key(cx, expr, account_expr))
}

fn compares_key<'tcx>(
cx: &LateContext<'tcx>,
expr: &Expr<'tcx>,
account_expr: &Expr<'tcx>,
field: &str,
) -> bool {
if_chain! {
if let ExprKind::Field(object, field_name) = expr.kind;
// TODO: add check for key, is_signer
if field_name.as_str() == field;
let mut spanless_eq = SpanlessEq::new(cx);
if spanless_eq.eq_expr(account_expr, object);
// check if the expr is comparison expression
if let ExprKind::Binary(op, lhs, rhs) = expr.kind;
// == or !=
if matches!(op.node, BinOpKind::Eq | BinOpKind::Ne);
// check if lhs or rhs accesses key of `account_expr`
if expr_accesses_key(cx, lhs, account_expr) || expr_accesses_key(cx, rhs, account_expr);
then {
true
} else {
Expand All @@ -230,6 +219,17 @@ fn uses_given_field<'tcx>(
}
}

// Return true if the expr access key of account_expr(AccountInfo)
fn expr_accesses_key<'tcx>(
cx: &LateContext<'tcx>,
expr: &Expr<'tcx>,
account_expr: &Expr<'tcx>,
) -> bool {
// Anchor AccountInfo: `.key()` and Solana AccountInfo: `.key` field.
calls_method_on_expr(cx, expr, account_expr, &paths::ANCHOR_LANG_KEY)
|| uses_given_field(cx, expr, account_expr, "key")
}

/// Checks if `expr` is a method call of `path` on `account_expr`
fn calls_method_on_expr<'tcx>(
cx: &LateContext<'tcx>,
Expand All @@ -251,41 +251,41 @@ fn calls_method_on_expr<'tcx>(
}
}

// Return true if the expr access key of account_expr(AccountInfo)
fn expr_accesses_key<'tcx>(
/// Checks if `expr` is references `field` on `account_expr`
fn uses_given_field<'tcx>(
cx: &LateContext<'tcx>,
expr: &Expr<'tcx>,
account_expr: &Expr<'tcx>,
field: &str,
) -> bool {
// Anchor AccountInfo: `.key()` and Solana AccountInfo: `.key` field.
calls_method_on_expr(cx, expr, account_expr, &paths::ANCHOR_LANG_KEY)
|| uses_given_field(cx, expr, account_expr, "key")
}

fn contains_key_check<'tcx>(
cx: &LateContext<'tcx>,
body: &'tcx Body<'tcx>,
account_expr: &Expr<'tcx>,
) -> bool {
visit_expr_no_bodies(body.value, |expr| compares_key(cx, expr, account_expr))
if_chain! {
if let ExprKind::Field(object, field_name) = expr.kind;
// TODO: add check for key, is_signer
if field_name.as_str() == field;
let mut spanless_eq = SpanlessEq::new(cx);
if spanless_eq.eq_expr(account_expr, object);
then {
true
} else {
false
}
}
}

fn compares_key<'tcx>(
/// if `expr` is a method call of `def_path` return the receiver else None
fn is_expr_method_call<'tcx>(
cx: &LateContext<'tcx>,
expr: &Expr<'tcx>,
account_expr: &Expr<'tcx>,
) -> bool {
def_path: &[&str],
) -> Option<&'tcx Expr<'tcx>> {
if_chain! {
// check if the expr is comparison expression
if let ExprKind::Binary(op, lhs, rhs) = expr.kind;
// == or !=
if matches!(op.node, BinOpKind::Eq | BinOpKind::Ne);
// check if lhs or rhs accesses key of `account_expr`
if expr_accesses_key(cx, lhs, account_expr) || expr_accesses_key(cx, rhs, account_expr);
if let ExprKind::MethodCall(_, recv, _, _) = expr.kind;
if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
if match_def_path(cx, def_id, def_path);
then {
true
Some(recv)
} else {
false
None
}
}
}
Expand Down

0 comments on commit 75b9c81

Please sign in to comment.