From b75a512fa762b4bd3d8ee23401f095af7c21532f Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 28 May 2015 00:35:56 +0300 Subject: [PATCH] Prevent comparison and dereferencing of raw pointers in constexprs Fixes #25826. --- src/librustc/diagnostics.rs | 2 ++ src/librustc/middle/check_const.rs | 31 +++++++++++++++++++----- src/test/compile-fail/deref-ptr-const.rs | 16 ++++++++++++ src/test/compile-fail/issue-17458.rs | 2 +- src/test/compile-fail/issue-25768.rs | 15 ++++++++++++ src/test/compile-fail/issue-25826.rs | 16 ++++++++++++ 6 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 src/test/compile-fail/deref-ptr-const.rs create mode 100644 src/test/compile-fail/issue-25768.rs create mode 100644 src/test/compile-fail/issue-25826.rs diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 9d459027bf5cd..6d40d79c16bd9 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -892,6 +892,8 @@ register_diagnostics! { E0316, // nested quantification of lifetimes E0370, // discriminant overflow E0378, // method calls limited to constant inherent methods + E0380, // pointer comparison in const-expr + E0381, // pointer dereference in const-expr E0394 // cannot refer to other statics by value, use the address-of // operator or a constant instead } diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index c54517e00173b..3723d82b59e4d 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -536,11 +536,32 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, "allocations are not allowed in {}s", v.msg()); } } - ast::ExprUnary(ast::UnDeref, ref ptr) => { - match ty::node_id_to_type(v.tcx, ptr.id).sty { + ast::ExprUnary(op, ref inner) => { + match ty::node_id_to_type(v.tcx, inner.id).sty { ty::ty_ptr(_) => { - // This shouldn't be allowed in constants at all. + assert!(op == ast::UnDeref); + + v.add_qualif(ConstQualif::NOT_CONST); + if v.mode != Mode::Var { + span_err!(v.tcx.sess, e.span, E0381, + "raw pointers cannot be dereferenced in {}s", v.msg()); + } + } + _ => {} + } + } + ast::ExprBinary(op, ref lhs, _) => { + match ty::node_id_to_type(v.tcx, lhs.id).sty { + ty::ty_ptr(_) => { + assert!(op.node == ast::BiEq || op.node == ast::BiNe || + op.node == ast::BiLe || op.node == ast::BiLt || + op.node == ast::BiGe || op.node == ast::BiGt); + v.add_qualif(ConstQualif::NOT_CONST); + if v.mode != Mode::Var { + span_err!(v.tcx.sess, e.span, E0380, + "raw pointers cannot be compared in {}s", v.msg()); + } } _ => {} } @@ -553,7 +574,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, v.add_qualif(ConstQualif::NOT_CONST); if v.mode != Mode::Var { span_err!(v.tcx.sess, e.span, E0018, - "can't cast a pointer to an integer in {}s", v.msg()); + "raw pointers cannot be cast to integers in {}s", v.msg()); } } _ => {} @@ -695,8 +716,6 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, } ast::ExprBlock(_) | - ast::ExprUnary(..) | - ast::ExprBinary(..) | ast::ExprIndex(..) | ast::ExprField(..) | ast::ExprTupField(..) | diff --git a/src/test/compile-fail/deref-ptr-const.rs b/src/test/compile-fail/deref-ptr-const.rs new file mode 100644 index 0000000000000..477554e6aa93a --- /dev/null +++ b/src/test/compile-fail/deref-ptr-const.rs @@ -0,0 +1,16 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that you can't dereference raw pointers in constants. + +fn main() { + static C: u64 = unsafe {*(0xdeadbeef as *const u64)}; //~ ERROR E0381 + println!("{}", C); +} diff --git a/src/test/compile-fail/issue-17458.rs b/src/test/compile-fail/issue-17458.rs index a3a9e17cb3c06..f5b7a0c13b728 100644 --- a/src/test/compile-fail/issue-17458.rs +++ b/src/test/compile-fail/issue-17458.rs @@ -9,7 +9,7 @@ // except according to those terms. static X: usize = 0 as *const usize as usize; -//~^ ERROR: can't cast a pointer to an integer in statics +//~^ ERROR: raw pointers cannot be cast to integers in statics fn main() { assert_eq!(X, 0); diff --git a/src/test/compile-fail/issue-25768.rs b/src/test/compile-fail/issue-25768.rs new file mode 100644 index 0000000000000..d3f74e1eb45fc --- /dev/null +++ b/src/test/compile-fail/issue-25768.rs @@ -0,0 +1,15 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let y: *const str = ""; + y == y; //~ ERROR binary operation `==` cannot be applied + y < y; //~ ERROR binary operation `<` cannot be applied +} diff --git a/src/test/compile-fail/issue-25826.rs b/src/test/compile-fail/issue-25826.rs new file mode 100644 index 0000000000000..e11d462d89bd8 --- /dev/null +++ b/src/test/compile-fail/issue-25826.rs @@ -0,0 +1,16 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn id(t: T) -> T { t } +fn main() { + const A: bool = id:: as *const () < id:: as *const (); + //~^ ERROR E0380 raw pointers cannot be compared in constants + println!("{}", A); +}