@@ -319,9 +319,54 @@ impl SecurityVisitor {
319319 }
320320 }
321321
322+ fn analyze_field_access ( & mut self , expr : & Expr , field_expr : & syn:: ExprField ) {
323+ let field_name = field_expr. member . to_token_stream ( ) . to_string ( ) ;
324+ let receiver_str = quote:: quote!( #expr) . to_string ( ) ;
325+
326+ // Look for Solana account field access patterns
327+ if receiver_str. contains ( "account" ) {
328+ let line_num = self . get_line_number_for_pattern ( & format ! ( ".{}" , field_name) ) ;
329+
330+ match field_name. as_str ( ) {
331+ "owner" => {
332+ let mut solana_op = SolanaOperation {
333+ line : line_num,
334+ operation_type : "account_owner_access" . to_string ( ) ,
335+ account_validation : false ,
336+ signer_check : false ,
337+ pda_seeds : Vec :: new ( ) ,
338+ program_id_check : false ,
339+ owner_check : false , // Will be set to true if there's validation
340+ account_data_validation : false ,
341+ } ;
342+
343+ // This is just accessing the owner, not validating it
344+ // The test expects detection of missing validation
345+ self . solana_operations . push ( solana_op) ;
346+ }
347+ "data" | "lamports" | "key" => {
348+ let mut solana_op = SolanaOperation {
349+ line : line_num,
350+ operation_type : format ! ( "account_{}_access" , field_name) ,
351+ account_validation : false ,
352+ signer_check : false ,
353+ pda_seeds : Vec :: new ( ) ,
354+ program_id_check : false ,
355+ owner_check : false ,
356+ account_data_validation : false ,
357+ } ;
358+
359+ self . solana_operations . push ( solana_op) ;
360+ }
361+ _ => { }
362+ }
363+ }
364+ }
365+
322366 fn analyze_method_call ( & mut self , expr : & Expr ) {
323367 if let Expr :: MethodCall ( method_call) = expr {
324368 let method_name = method_call. method . to_string ( ) ;
369+ let receiver_str = quote:: quote!( #method_call) . to_string ( ) ;
325370 let line_num = self . get_line_number_for_pattern ( & format ! ( ".{}(" , method_name) ) ;
326371
327372 match method_name. as_str ( ) {
@@ -339,6 +384,28 @@ impl SecurityVisitor {
339384 context : "method_call" . to_string ( ) ,
340385 } ) ;
341386 }
387+ "borrow" | "borrow_mut" => {
388+ // Check if this is a Solana account data access
389+ if receiver_str. contains ( "account" ) && receiver_str. contains ( "data" ) {
390+ let mut solana_op = SolanaOperation {
391+ line : line_num,
392+ operation_type : "account_data_access" . to_string ( ) ,
393+ account_validation : false ,
394+ signer_check : false ,
395+ pda_seeds : Vec :: new ( ) ,
396+ program_id_check : false ,
397+ owner_check : false ,
398+ account_data_validation : false ,
399+ } ;
400+
401+ // Check if there's any signer validation in the context
402+ if receiver_str. contains ( "is_signer" ) {
403+ solana_op. signer_check = true ;
404+ }
405+
406+ self . solana_operations . push ( solana_op) ;
407+ }
408+ }
342409 _ => { }
343410 }
344411 }
@@ -493,6 +560,9 @@ impl<'ast> Visit<'ast> for SecurityVisitor {
493560 Expr :: Call ( _) => {
494561 self . analyze_function_call ( expr) ;
495562 }
563+ Expr :: Field ( field_expr) => {
564+ self . analyze_field_access ( expr, field_expr) ;
565+ }
496566 _ => { }
497567 }
498568
0 commit comments