Skip to content

Commit

Permalink
Add unchecked_shl/shr checks for intrinsics
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim committed Sep 6, 2018
1 parent 20ca025 commit 58af73c
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 4 deletions.
32 changes: 28 additions & 4 deletions src/librustc_mir/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
| "overflowing_add"
| "overflowing_sub"
| "overflowing_mul"
| "unchecked_shl"
| "unchecked_shr"
| "add_with_overflow"
| "sub_with_overflow"
| "mul_with_overflow" => {
Expand All @@ -116,8 +114,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
"overflowing_add" => (BinOp::Add, true),
"overflowing_sub" => (BinOp::Sub, true),
"overflowing_mul" => (BinOp::Mul, true),
"unchecked_shl" => (BinOp::Shl, true),
"unchecked_shr" => (BinOp::Shr, true),
"add_with_overflow" => (BinOp::Add, false),
"sub_with_overflow" => (BinOp::Sub, false),
"mul_with_overflow" => (BinOp::Mul, false),
Expand All @@ -129,6 +125,34 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
self.binop_with_overflow(bin_op, lhs, rhs, dest)?;
}
}
"unchecked_shl" | "unchecked_shr" => {
let bits = dest.layout.size.bytes() as u128 * 8;
let l = self.read_value(args[0])?;
let r = self.read_value(args[1])?;
let r_ty = substs.type_at(0);
let r_layout_of = self.layout_of(r_ty)?;
let r_val = r.to_scalar()?.to_bits(r_layout_of.size)?;
let bin_op = match intrinsic_name {
"unchecked_shl" => {
if r_val >= bits {
return err!(Intrinsic(
format!("Overflowing shift by {} in unchecked_shl", r_val),
));
}
BinOp::Shl
},
"unchecked_shr" => {
if r_val >= bits {
return err!(Intrinsic(
format!("Overflowing shift by {} in unchecked_shr", r_val),
));
}
BinOp::Shr
},
_ => bug!("Already checked for int ops")
};
self.binop_ignore_overflow(bin_op, l, r, dest)?;
}
"transmute" => {
// Go through an allocation, to make sure the completely different layouts
// do not pose a problem. (When the user transmutes through a union,
Expand Down
21 changes: 21 additions & 0 deletions src/test/ui/consts/const-int-unchecked.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2018 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(core_intrinsics)]

use std::intrinsics;

const SHR: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) };
//^~ ERROR: Overflowing shift by 8 in unchecked_shr
const SHL: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) };
//^~ ERROR: Overflowing shift by 8 in unchecked_shl

fn main() {
}
20 changes: 20 additions & 0 deletions src/test/ui/consts/const-int-unchecked.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error: this constant cannot be used
--> $DIR/const-int-unchecked.rs:15:1
|
LL | const SHR: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^^^
| |
| Overflowing shift by 8 in unchecked_shr
|
= note: #[deny(const_err)] on by default

error: this constant cannot be used
--> $DIR/const-int-unchecked.rs:17:1
|
LL | const SHL: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^^^
| |
| Overflowing shift by 8 in unchecked_shl

error: aborting due to 2 previous errors

0 comments on commit 58af73c

Please sign in to comment.