-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Compiler-v2] check access for structs #12821
Conversation
@@ -335,7 +335,7 @@ const TEST_CONFIGS: Lazy<BTreeMap<&str, TestConfig>> = Lazy::new(|| { | |||
include: vec!["/acquires-checker/"], | |||
exclude: vec![], | |||
exp_suffix: None, | |||
options: opts.clone(), | |||
options: opts.clone().set_experiment(Experiment::ACCESS_CHECK, false), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
skip access check for acquires-checker so that the error messages remain the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add this as a comment please?
@@ -430,34 +433,3 @@ move-compiler/tests/move_check/typing/while_body.exp move-compiler-v2/tests/ch | |||
move-compiler/tests/move_check/typing/while_body_invalid.exp move-compiler-v2/tests/checking/typing/while_body_invalid.exp | |||
move-compiler/tests/move_check/typing/while_condition.exp move-compiler-v2/tests/checking/typing/while_condition.exp | |||
move-compiler/tests/move_check/typing/while_condition_invalid.exp move-compiler-v2/tests/checking/typing/while_condition_invalid.exp | |||
move-compiler/tests/move_check/parser/aptos_stdlib_attributes.exp move-compiler-v2/tests/checking/attributes/aptos_stdlib_attributes.exp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After Brian's PR to fix the update tool is landed, these will be recovered.
@@ -225,17 +222,3 @@ move-compiler/tests/move_check/verification/{ | |||
single_module_invalid.move, | |||
single_module_valid.move, | |||
} | |||
move-compiler/tests/move_check/unit_test/{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After Brian's PR to fix the update tool is landed, these will be recovered.
382c47f
to
eb2c259
Compare
error: Invalid pack operation on external type D::G | ||
┌─ tests/visibility-checker/pack_unpack_structs.move:13:16 | ||
│ | ||
13 │ public fun foo(): C::T { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice if we could show the module header lines, since that's the controlling factor. Not sure we have those Locs easily available, though.
Please file an issue to follow up on that. It will require adding a field to ModuleData
similar to the id_loc
field of FunctionData
. To initialize that will require adding a parameter id_loc
to ModuleBuilder::translate()
. Call sites to that should have it available.
mid: &ModuleId, | ||
pat: &Pattern, | ||
) { | ||
match pat { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can probably simplify this a bit by using Pattern::visit_pre_post
.
eb2c259
to
2c35dcd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good so far.
env.diag_with_labels(Severity::Error, fun_loc, &msg, call_details); | ||
} | ||
|
||
/// check a struct can only be accessed within the module that defines it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a bit misleading to say "struct can only be accessed within the module that defines it" -> struct types are indeed accessible outside of the module, just that certain privileged operations are limited to the defining module (https://aptos.dev/move/book/structs-and-resources#privileged-struct-operations).
Please update docs and maybe function names?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
/// For all function in target modules: | ||
/// | ||
/// If `before_inlining`, then | ||
/// - check that all function calls involving inline functions are accessible; | ||
/// - warn about unused private functions | ||
/// Otherwise (`!before_inlining`): | ||
/// - check that all function calls *not* involving inline functions are accessible. | ||
/// - check structs are not accessed across the module boundary. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same comment as above (certain privileged operations on structs cannot be done across module boundary).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
id, | ||
"called", | ||
format!( | ||
"Invalid storage operation on external type `{}`", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you also fix #12820 with this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think that's the case
| Operation::BorrowGlobal(_) | ||
| Operation::MoveFrom | ||
| Operation::MoveTo | ||
if env.get_node_instantiation(*id)[0].get_struct(env).is_some() => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of doing this check here (the if condition), and then redoing a portion of it again inside, it may be cleaner to move the check inside (and not repeat some of the code).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
"called", | ||
format!( | ||
"Invalid storage operation on external type `{}`", | ||
struct_env.get_full_name_str() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could perhaps provide more information here to be more heipful to the user, similar to what we do with inaccessible calls (see third_party/move/move-compiler-v2/tests/visibility-checker/v1-typing/module_call_entry_function_was_invalid.exp
for an example)?
Maybe we could have something along the lines of: "Invalid operation: storage operation <blah>
on type <blah>
can only be done within the defining module <blah>
" ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
id, | ||
"accessed", | ||
format!( | ||
"Invalid access of field `{}` on external type `{}`", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar note as above.
Maybe we could have something along the lines of: "Invalid field access: the field blah
on type blah
can only be accessed withing the defining module blah
".
These can be of respite especially in the presence of inlining.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
id, | ||
"packed", | ||
format!( | ||
"Invalid pack operation on external type {}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can additionally say that only the module defining the struct can create (pack) it.
I find "external type" to provide insufficient guidance to a user (it is external to what? to the module, but that is not clear and can get muddied especially with inlining and where we would point the primary error at).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
}, | ||
_ => {}, | ||
}, | ||
ExpData::Assign(_, pat, _) | ExpData::Block(_, pat, _, _) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like Lambda
also has a pattern, is that a missing case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check is performed after inlining. Do we still have Lambda then? cc @brmataptos
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, no, but you can throw it in if you want to handle future cases, maybe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
}) | ||
} | ||
} // end 0x42::token | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we add more inline tests, specifically, inline functions that do each of the restricted cases? We may then want to improve error messages for the inlined cases (like is done for visibility of calls).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -335,7 +335,7 @@ const TEST_CONFIGS: Lazy<BTreeMap<&str, TestConfig>> = Lazy::new(|| { | |||
include: vec!["/acquires-checker/"], | |||
exclude: vec![], | |||
exp_suffix: None, | |||
options: opts.clone(), | |||
options: opts.clone().set_experiment(Experiment::ACCESS_CHECK, false), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add this as a comment please?
2c35dcd
to
4844c17
Compare
4844c17
to
e97909a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice! LGTM.
note: I have a comment on a minor typo.
|
||
/// check privileged operations on a struct such as storage operation, pack/unpack and field accesses | ||
/// can only be performed within the module that defines it. | ||
fn check_previleged_operations_on_structs(env: &GlobalEnv, fun_env: &FunctionEnv) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fn check_previleged_operations_on_structs(env: &GlobalEnv, fun_env: &FunctionEnv) { | |
fn check_privileged_operations_on_structs(env: &GlobalEnv, fun_env: &FunctionEnv) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
e97909a
to
541bc7b
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
✅ Forge suite
|
✅ Forge suite
|
Description
This PR adds the check to guarantee a struct can only be accessed within the module that defines it.
Close #11014
Close #12820
Type of Change
Which Components or Systems Does This Change Impact?
How Has This Been Tested?
Key Areas to Review
Whether all ways of accessing a struct are covered.
Checklist