From 3da28dbc5fada6b8edf1b7e86dced92f13924474 Mon Sep 17 00:00:00 2001 From: Sammy Harris <41593264+stegaBOB@users.noreply.github.com> Date: Thu, 13 Oct 2022 23:08:02 -0400 Subject: [PATCH] fix: ignore non Accounts in safety checks (#2201) --- lang/syn/src/parser/context.rs | 16 +++++++++- .../programs/ignore-non-accounts/Cargo.toml | 19 ++++++++++++ .../programs/ignore-non-accounts/Xargo.toml | 2 ++ .../programs/ignore-non-accounts/src/lib.rs | 30 +++++++++++++++++++ tests/safety-checks/test.sh | 12 +++++++- 5 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 tests/safety-checks/programs/ignore-non-accounts/Cargo.toml create mode 100644 tests/safety-checks/programs/ignore-non-accounts/Xargo.toml create mode 100644 tests/safety-checks/programs/ignore-non-accounts/src/lib.rs diff --git a/lang/syn/src/parser/context.rs b/lang/syn/src/parser/context.rs index 8e0fb2a30..190f34072 100644 --- a/lang/syn/src/parser/context.rs +++ b/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 { + 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 { diff --git a/tests/safety-checks/programs/ignore-non-accounts/Cargo.toml b/tests/safety-checks/programs/ignore-non-accounts/Cargo.toml new file mode 100644 index 000000000..e8de691a5 --- /dev/null +++ b/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" } diff --git a/tests/safety-checks/programs/ignore-non-accounts/Xargo.toml b/tests/safety-checks/programs/ignore-non-accounts/Xargo.toml new file mode 100644 index 000000000..475fb71ed --- /dev/null +++ b/tests/safety-checks/programs/ignore-non-accounts/Xargo.toml @@ -0,0 +1,2 @@ +[target.bpfel-unknown-unknown.dependencies.std] +features = [] diff --git a/tests/safety-checks/programs/ignore-non-accounts/src/lib.rs b/tests/safety-checks/programs/ignore-non-accounts/src/lib.rs new file mode 100644 index 000000000..30f4bea6b --- /dev/null +++ b/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) -> 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>, +} diff --git a/tests/safety-checks/test.sh b/tests/safety-checks/test.sh index f10d6850c..872d6c1f2 100755 --- a/tests/safety-checks/test.sh +++ b/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."