@@ -12,7 +12,7 @@ use if_chain::if_chain;
12
12
use rustc_hir:: {
13
13
def_id:: LocalDefId ,
14
14
intravisit:: { walk_expr, FnKind , Visitor } ,
15
- Body , Expr , ExprKind , FnDecl ,
15
+ Body , Expr , ExprKind , FnDecl , QPath ,
16
16
} ;
17
17
use rustc_lint:: { LateContext , LateLintPass } ;
18
18
use rustc_middle:: ty;
@@ -108,6 +108,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for AccountUses<'cx, 'tcx> {
108
108
if !is_call_to_clone( self . cx, expr) ;
109
109
let ty = self . cx. typeck_results( ) . expr_ty( expr) ;
110
110
if match_type( self . cx, ty, & paths:: SOLANA_PROGRAM_ACCOUNT_INFO ) ;
111
+ if !is_expr_local_variable( expr) ;
111
112
if !is_safe_to_account_info( self . cx, expr) ;
112
113
let mut spanless_eq = SpanlessEq :: new( self . cx) ;
113
114
if !self . uses. iter( ) . any( |e| spanless_eq. eq_expr( e, expr) ) ;
@@ -119,6 +120,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for AccountUses<'cx, 'tcx> {
119
120
}
120
121
}
121
122
123
+ // s3v3ru5: the following check removes duplicate warnings where lint would report both `x` and `x.clone()` expressions.
122
124
/// Return true if the expr is a method call to clone else false
123
125
fn is_call_to_clone < ' tcx > ( cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' tcx > ) -> bool {
124
126
if_chain ! {
@@ -133,6 +135,24 @@ fn is_call_to_clone<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> boo
133
135
}
134
136
}
135
137
138
+ // s3v3ru5: if a local variable is of type AccountInfo, the rhs of the let statement assigning to variable
139
+ // will be of type AccountInfo. The lint would check that expression and there is no need for checking the
140
+ // local variable as well.
141
+ // This removes the false positives of following pattern:
142
+ // `let x = {Account, Program, ...verified structs}.to_account_info()`,
143
+ // the lint reports uses of `x`. Having this check would remove such false positives.
144
+ fn is_expr_local_variable < ' tcx > ( expr : & ' tcx Expr < ' tcx > ) -> bool {
145
+ if_chain ! {
146
+ if let ExprKind :: Path ( QPath :: Resolved ( None , path) ) = expr. kind;
147
+ if path. segments. len( ) == 1 ;
148
+ then {
149
+ true
150
+ } else {
151
+ false
152
+ }
153
+ }
154
+ }
155
+
136
156
// smoelius: See: https://github.com/crytic/solana-lints/issues/31
137
157
fn is_safe_to_account_info < ' tcx > ( cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' tcx > ) -> bool {
138
158
if_chain ! {
@@ -158,6 +178,8 @@ fn is_safe_to_account_info<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>)
158
178
& paths:: ANCHOR_LANG_ACCOUNT_LOADER ,
159
179
& paths:: ANCHOR_LANG_SIGNER ,
160
180
& paths:: ANCHOR_LANG_SYSVAR ,
181
+ // s3v3ru5: The following line will remove duplicate warnings where lint reports both `x` and `x.to_account_info()` when x is of type Anchor's AccountInfo.
182
+ & paths:: SOLANA_PROGRAM_ACCOUNT_INFO ,
161
183
] ,
162
184
)
163
185
. is_some( ) ;
0 commit comments