From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1643) id 71B45385841D; Thu, 28 Jul 2022 07:53:19 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 71B45385841D Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Thomas Schwinge To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/rust/master] unsafe: Forbid use of certain static values outside of unsafe contexts X-Act-Checkin: gcc X-Git-Author: Arthur Cohen X-Git-Refname: refs/heads/devel/rust/master X-Git-Oldrev: e7b6a9ee16ae495a858a694d53b8c74548f5bbdd X-Git-Newrev: f4e4c2444fc10f7952fc4dffceb9e3a7e85ed973 Message-Id: <20220728075319.71B45385841D@sourceware.org> Date: Thu, 28 Jul 2022 07:53:19 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 28 Jul 2022 07:53:19 -0000 https://gcc.gnu.org/g:f4e4c2444fc10f7952fc4dffceb9e3a7e85ed973 commit f4e4c2444fc10f7952fc4dffceb9e3a7e85ed973 Author: Arthur Cohen Date: Mon Jul 25 13:30:27 2022 +0200 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 Diff: --- gcc/rust/checks/errors/rust-unsafe-checker.cc | 78 +++++++++++++++++++++++++-- gcc/rust/checks/errors/rust-unsafe-checker.h | 9 ++++ gcc/testsuite/rust/compile/unsafe1.rs | 14 +++++ gcc/testsuite/rust/compile/unsafe2.rs | 16 ++++++ 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 def3cc11b7a..d234179f2fa 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 (maybe_static); + if (item->get_item_kind () == Item::ItemKind::Static) + { + auto static_item = static_cast (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 (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 3c817073993..38b9019e3b7 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 00000000000..9cd3f6b4bf2 --- /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 00000000000..e03e4bc59f4 --- /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 00000000000..56aec76008a --- /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; + } +}