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

This commit is contained in:
Sammy Harris 2022-10-13 23:08:02 -04:00 committed by GitHub
parent 5647510615
commit 3da28dbc5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 77 additions and 2 deletions

View File

@ -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 {

View File

@ -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" }

View File

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

View File

@ -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>,
}

View File

@ -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."