Skip to content

Commit 58af73c

Browse files
author
Tim
committed
Add unchecked_shl/shr checks for intrinsics
1 parent 20ca025 commit 58af73c

File tree

3 files changed

+69
-4
lines changed

3 files changed

+69
-4
lines changed

src/librustc_mir/interpret/intrinsics.rs

+28-4
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
105105
| "overflowing_add"
106106
| "overflowing_sub"
107107
| "overflowing_mul"
108-
| "unchecked_shl"
109-
| "unchecked_shr"
110108
| "add_with_overflow"
111109
| "sub_with_overflow"
112110
| "mul_with_overflow" => {
@@ -116,8 +114,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
116114
"overflowing_add" => (BinOp::Add, true),
117115
"overflowing_sub" => (BinOp::Sub, true),
118116
"overflowing_mul" => (BinOp::Mul, true),
119-
"unchecked_shl" => (BinOp::Shl, true),
120-
"unchecked_shr" => (BinOp::Shr, true),
121117
"add_with_overflow" => (BinOp::Add, false),
122118
"sub_with_overflow" => (BinOp::Sub, false),
123119
"mul_with_overflow" => (BinOp::Mul, false),
@@ -129,6 +125,34 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
129125
self.binop_with_overflow(bin_op, lhs, rhs, dest)?;
130126
}
131127
}
128+
"unchecked_shl" | "unchecked_shr" => {
129+
let bits = dest.layout.size.bytes() as u128 * 8;
130+
let l = self.read_value(args[0])?;
131+
let r = self.read_value(args[1])?;
132+
let r_ty = substs.type_at(0);
133+
let r_layout_of = self.layout_of(r_ty)?;
134+
let r_val = r.to_scalar()?.to_bits(r_layout_of.size)?;
135+
let bin_op = match intrinsic_name {
136+
"unchecked_shl" => {
137+
if r_val >= bits {
138+
return err!(Intrinsic(
139+
format!("Overflowing shift by {} in unchecked_shl", r_val),
140+
));
141+
}
142+
BinOp::Shl
143+
},
144+
"unchecked_shr" => {
145+
if r_val >= bits {
146+
return err!(Intrinsic(
147+
format!("Overflowing shift by {} in unchecked_shr", r_val),
148+
));
149+
}
150+
BinOp::Shr
151+
},
152+
_ => bug!("Already checked for int ops")
153+
};
154+
self.binop_ignore_overflow(bin_op, l, r, dest)?;
155+
}
132156
"transmute" => {
133157
// Go through an allocation, to make sure the completely different layouts
134158
// do not pose a problem. (When the user transmutes through a union,
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(core_intrinsics)]
12+
13+
use std::intrinsics;
14+
15+
const SHR: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) };
16+
//^~ ERROR: Overflowing shift by 8 in unchecked_shr
17+
const SHL: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) };
18+
//^~ ERROR: Overflowing shift by 8 in unchecked_shl
19+
20+
fn main() {
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: this constant cannot be used
2+
--> $DIR/const-int-unchecked.rs:15:1
3+
|
4+
LL | const SHR: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) };
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^^^
6+
| |
7+
| Overflowing shift by 8 in unchecked_shr
8+
|
9+
= note: #[deny(const_err)] on by default
10+
11+
error: this constant cannot be used
12+
--> $DIR/const-int-unchecked.rs:17:1
13+
|
14+
LL | const SHL: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) };
15+
| ^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------------^^^
16+
| |
17+
| Overflowing shift by 8 in unchecked_shl
18+
19+
error: aborting due to 2 previous errors
20+

0 commit comments

Comments
 (0)