diff options
author | Arthur Cohen <arthur.cohen@embecosm.com> | 2022-07-25 13:30:27 +0200 |
---|---|---|
committer | Arthur Cohen <arthur.cohen@embecosm.com> | 2022-07-27 15:31:42 +0200 |
commit | f4e4c2444fc10f7952fc4dffceb9e3a7e85ed973 (patch) | |
tree | 0d837389aee6635dc75a7b1a78de2a38a268e958 /gcc | |
parent | e7b6a9ee16ae495a858a694d53b8c74548f5bbdd (diff) | |
download | gcc-f4e4c2444fc10f7952fc4dffceb9e3a7e85ed973.zip gcc-f4e4c2444fc10f7952fc4dffceb9e3a7e85ed973.tar.gz gcc-f4e4c2444fc10f7952fc4dffceb9e3a7e85ed973.tar.bz2 |
unsafe: Forbid use of certain static values outside of unsafe contexts
Using a mutable static or an extern static requires an unsafe function
or block
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/checks/errors/rust-unsafe-checker.cc | 78 | ||||
-rw-r--r-- | gcc/rust/checks/errors/rust-unsafe-checker.h | 9 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/unsafe1.rs | 14 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/unsafe2.rs | 16 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/unsafe3.rs | 10 |
5 files changed, 123 insertions, 4 deletions
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc b/gcc/rust/checks/errors/rust-unsafe-checker.cc index def3cc1..d234179 100644 --- a/gcc/rust/checks/errors/rust-unsafe-checker.cc +++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc @@ -25,7 +25,10 @@ namespace Rust { namespace HIR { -UnsafeChecker::UnsafeChecker () : context (*Resolver::TypeCheckContext::get ()) +UnsafeChecker::UnsafeChecker () + : context (*Resolver::TypeCheckContext::get ()), + resolver (*Resolver::Resolver::get ()), + mappings (*Analysis::Mappings::get ()) {} void @@ -35,6 +38,47 @@ UnsafeChecker::go (HIR::Crate &crate) item->accept_vis (*this); } +static void +check_static_mut (HIR::Item *maybe_static, Location locus) +{ + if (maybe_static->get_hir_kind () == Node::BaseKind::VIS_ITEM) + { + auto item = static_cast<Item *> (maybe_static); + if (item->get_item_kind () == Item::ItemKind::Static) + { + auto static_item = static_cast<StaticItem *> (item); + if (static_item->is_mut ()) + rust_error_at ( + locus, "use of mutable static requires unsafe function or block"); + } + } +} + +static void +check_extern_static (HIR::ExternalItem *maybe_static, Location locus) +{ + if (maybe_static->get_extern_kind () == ExternalItem::ExternKind::Static) + rust_error_at (locus, + "use of extern static requires unsafe function or block"); +} + +void +UnsafeChecker::check_use_of_static (HirId node_id, Location locus) +{ + if (is_unsafe_context ()) + return; + + auto maybe_static_mut = mappings.lookup_hir_item (node_id); + auto maybe_extern_static = mappings.lookup_hir_extern_item (node_id); + + if (maybe_static_mut) + check_static_mut (maybe_static_mut, locus); + + if (maybe_extern_static) + check_extern_static (static_cast<ExternalItem *> (maybe_extern_static), + locus); +} + void UnsafeChecker::push_unsafe (HirId id) { @@ -60,7 +104,18 @@ UnsafeChecker::is_unsafe_context () void UnsafeChecker::visit (IdentifierExpr &ident_expr) -{} +{ + NodeId ast_node_id = ident_expr.get_mappings ().get_nodeid (); + NodeId ref_node_id; + HirId definition_id; + + if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id)) + return; + + rust_assert (mappings.lookup_node_to_hir (ref_node_id, &definition_id)); + + check_use_of_static (definition_id, ident_expr.get_locus ()); +} void UnsafeChecker::visit (Lifetime &lifetime) @@ -72,7 +127,18 @@ UnsafeChecker::visit (LifetimeParam &lifetime_param) void UnsafeChecker::visit (PathInExpression &path) -{} +{ + NodeId ast_node_id = path.get_mappings ().get_nodeid (); + NodeId ref_node_id; + HirId definition_id; + + if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id)) + return; + + rust_assert (mappings.lookup_node_to_hir (ref_node_id, &definition_id)); + + check_use_of_static (definition_id, path.get_locus ()); +} void UnsafeChecker::visit (TypePathSegment &segment) @@ -253,7 +319,11 @@ UnsafeChecker::visit (StructExprStructBase &expr) void UnsafeChecker::visit (CallExpr &expr) -{} +{ + if (expr.has_params ()) + for (auto &arg : expr.get_arguments ()) + arg->accept_vis (*this); +} void UnsafeChecker::visit (MethodCallExpr &expr) diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.h b/gcc/rust/checks/errors/rust-unsafe-checker.h index 3c81707..38b9019 100644 --- a/gcc/rust/checks/errors/rust-unsafe-checker.h +++ b/gcc/rust/checks/errors/rust-unsafe-checker.h @@ -20,6 +20,7 @@ #define RUST_UNSAFE_CHECKER_H #include "rust-hir-visitor.h" +#include "rust-name-resolver.h" #include "rust-hir-type-check.h" namespace Rust { @@ -51,7 +52,15 @@ private: */ bool is_unsafe_context (); + /** + * Check if a mutable static or external static item is used outside of an + * unsafe context + */ + void check_use_of_static (HirId node_id, Location locus); + Resolver::TypeCheckContext &context; + Resolver::Resolver resolver; + Analysis::Mappings mappings; virtual void visit (IdentifierExpr &ident_expr) override; virtual void visit (Lifetime &lifetime) override; diff --git a/gcc/testsuite/rust/compile/unsafe1.rs b/gcc/testsuite/rust/compile/unsafe1.rs new file mode 100644 index 0000000..9cd3f6b --- /dev/null +++ b/gcc/testsuite/rust/compile/unsafe1.rs @@ -0,0 +1,14 @@ +fn foo(_a: &i32) {} +fn bar(_a: i32) {} + +static mut a: i32 = 15; + +fn main() { + foo(&a); // { dg-error "use of mutable static" } + bar(a); // { dg-error "use of mutable static" } + + unsafe { + foo(&a); + bar(a); + } +} diff --git a/gcc/testsuite/rust/compile/unsafe2.rs b/gcc/testsuite/rust/compile/unsafe2.rs new file mode 100644 index 0000000..e03e4bc --- /dev/null +++ b/gcc/testsuite/rust/compile/unsafe2.rs @@ -0,0 +1,16 @@ +fn foo(_a: &i32) {} +fn bar(_a: i32) {} + +mod inner { + pub static mut a: i32 = 15; +} + +fn main() { + foo(&inner::a); // { dg-error "use of mutable static" } + bar(inner::a); // { dg-error "use of mutable static" } + + unsafe { + foo(&inner::a); + bar(inner::a); + } +} diff --git a/gcc/testsuite/rust/compile/unsafe3.rs b/gcc/testsuite/rust/compile/unsafe3.rs new file mode 100644 index 0000000..56aec76 --- /dev/null +++ b/gcc/testsuite/rust/compile/unsafe3.rs @@ -0,0 +1,10 @@ +extern "C" { + static VALUE: char; +} + +fn main() { + let _ = VALUE; // { dg-error "use of extern static" } + unsafe { + let _ = VALUE; + } +} |