Explorar o código

fix: ignore non Accounts in safety checks (#2201)

Sammy Harris %!s(int64=3) %!d(string=hai) anos
pai
achega
3da28dbc5f

+ 15 - 1
lang/syn/src/parser/context.rs

@@ -68,7 +68,7 @@ impl CrateContext {
         {}:{}:{}
         Struct field "{}" is unsafe, but is not documented.
         Please add a `/// CHECK:` doc comment explaining why no checks through types are necessary.
-        See https://book.anchor-lang.com/anchor_in_depth/the_accounts_struct.html#safety-checks for more information.
+        See https://www.anchor-lang.com/docs/the-accounts-struct#safety-checks for more information.
                     "#,
                         ctx.file.canonicalize().unwrap().display(),
                         span.start().line,
@@ -222,7 +222,21 @@ impl ParsedModule {
     }
 
     fn unsafe_struct_fields(&self) -> impl Iterator<Item = &syn::Field> {
+        let accounts_filter = |item_struct: &&syn::ItemStruct| {
+            item_struct.attrs.iter().any(|attr| {
+                match attr.parse_meta() {
+                    Ok(syn::Meta::List(syn::MetaList{path, nested, ..})) => {
+                        path.is_ident("derive") && nested.iter().any(|nested| {
+                            matches!(nested, syn::NestedMeta::Meta(syn::Meta::Path(path)) if path.is_ident("Accounts"))
+                        })
+                    }
+                    _ => false
+                }
+            })
+        };
+
         self.structs()
+            .filter(accounts_filter)
             .flat_map(|s| &s.fields)
             .filter(|f| match &f.ty {
                 syn::Type::Path(syn::TypePath {

+ 19 - 0
tests/safety-checks/programs/ignore-non-accounts/Cargo.toml

@@ -0,0 +1,19 @@
+[package]
+name = "ignore-non-accounts"
+version = "0.1.0"
+description = "Created with Anchor"
+edition = "2018"
+
+[lib]
+crate-type = ["cdylib", "lib"]
+name = "ignore_non_accounts"
+
+[features]
+no-entrypoint = []
+no-idl = []
+no-log-ix-name = []
+cpi = ["no-entrypoint"]
+default = []
+
+[dependencies]
+anchor-lang = { path = "../../../../lang" }

+ 2 - 0
tests/safety-checks/programs/ignore-non-accounts/Xargo.toml

@@ -0,0 +1,2 @@
+[target.bpfel-unknown-unknown.dependencies.std]
+features = []

+ 30 - 0
tests/safety-checks/programs/ignore-non-accounts/src/lib.rs

@@ -0,0 +1,30 @@
+use anchor_lang::prelude::*;
+
+declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
+
+#[program]
+pub mod ignore_non_accounts {
+    use super::*;
+    pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
+        Ok(())
+    }
+}
+
+#[derive(Accounts)]
+pub struct Initialize<'info> {
+    /// CHECK:
+    checked1: UncheckedAccount<'info>,
+    /// CHECK:
+    checked2: AccountInfo<'info>,
+}
+
+#[derive(Debug)]
+pub struct ShouldIgnore1<'info> {
+    unchecked1: UncheckedAccount<'info>,
+    unchecked2: AccountInfo<'info>,
+}
+
+pub struct ShouldIgnore2<'info> {
+    unchecked1: UncheckedAccount<'info>,
+    unchecked2: AccountInfo<'info>,
+}

+ 11 - 1
tests/safety-checks/test.sh

@@ -24,4 +24,14 @@ if ! [[ $output =~ "Struct field \"unchecked\" is unsafe" ]]; then
 fi
 popd
 
-echo "Success. As expected, all builds failed."
+#
+# Build the control variant.
+#
+pushd programs/ignore-non-accounts/
+if ! anchor build ; then
+   echo "Error: anchor build failed when it shouldn't have"
+   exit 1
+fi
+popd
+
+echo "Success. As expected, all builds failed that were supposed to fail."