public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] unsafe: Forbid use of certain static values outside of unsafe contexts
@ 2022-07-28  7:53 Thomas Schwinge
  0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2022-07-28  7:53 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:f4e4c2444fc10f7952fc4dffceb9e3a7e85ed973

commit f4e4c2444fc10f7952fc4dffceb9e3a7e85ed973
Author: Arthur Cohen <arthur.cohen@embecosm.com>
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<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 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;
+    }
+}


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-07-28  7:53 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-28  7:53 [gcc/devel/rust/master] unsafe: Forbid use of certain static values outside of unsafe contexts Thomas Schwinge

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).