Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
e0320b5f
R
Rust
项目概览
int
/
Rust
11 个月 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
e0320b5f
编写于
5月 06, 2020
作者:
R
Ralf Jung
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
validation: port more checks to the pattern-based macro (and give it the shorter name)
上级
04689e22
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
54 addition
and
30 deletion
+54
-30
src/librustc_middle/mir/interpret/error.rs
src/librustc_middle/mir/interpret/error.rs
+5
-0
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/operand.rs
+1
-1
src/librustc_mir/interpret/validity.rs
src/librustc_mir/interpret/validity.rs
+48
-29
未找到文件。
src/librustc_middle/mir/interpret/error.rs
浏览文件 @
e0320b5f
...
...
@@ -380,6 +380,8 @@ pub enum UndefinedBehaviorInfo {
InvalidDiscriminant
(
ScalarMaybeUndef
),
/// Using a pointer-not-to-a-function as function pointer.
InvalidFunctionPointer
(
Pointer
),
/// Using a string that is not valid UTF-8,
InvalidStr
(
std
::
str
::
Utf8Error
),
/// Using uninitialized data where it is not allowed.
InvalidUndefBytes
(
Option
<
Pointer
>
),
/// Working with a local that is not currently live.
...
...
@@ -446,6 +448,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
InvalidFunctionPointer
(
p
)
=>
{
write!
(
f
,
"using {} as function pointer but it does not point to a function"
,
p
)
}
InvalidStr
(
err
)
=>
{
write!
(
f
,
"this string is not valid UTF-8: {}"
,
err
)
}
InvalidUndefBytes
(
Some
(
p
))
=>
write!
(
f
,
"reading uninitialized memory at {}, but this operation requires initialized memory"
,
...
...
src/librustc_mir/interpret/operand.rs
浏览文件 @
e0320b5f
...
...
@@ -328,7 +328,7 @@ pub fn read_str(&self, mplace: MPlaceTy<'tcx, M::PointerTag>) -> InterpResult<'t
let
len
=
mplace
.len
(
self
)
?
;
let
bytes
=
self
.memory
.read_bytes
(
mplace
.ptr
,
Size
::
from_bytes
(
len
))
?
;
let
str
=
::
std
::
str
::
from_utf8
(
bytes
)
.map_err
(|
err
|
err_ub
_format!
(
"this string is not valid UTF-8: {}"
,
err
))
?
;
.map_err
(|
err
|
err_ub
!
(
InvalidStr
(
err
)
))
?
;
Ok
(
str
)
}
...
...
src/librustc_mir/interpret/validity.rs
浏览文件 @
e0320b5f
...
...
@@ -38,12 +38,12 @@
}
/// Returns a validation failure for any Err value of $e.
// FIXME: Replace all usages of try_validation
! with try_validation_pat
!.
macro_rules!
try_validation
{
// FIXME: Replace all usages of try_validation
_catchall! with try_validation
!.
macro_rules!
try_validation
_catchall
{
(
$e:expr
,
$what:expr
,
$where:expr
$
(,
$expected:expr
)
?
)
=>
{{
try_validation
_pat!
(
$e
,
$where
,
{
try_validation
!
(
$e
,
$where
,
_
=>
{
"{}"
,
$what
}
$
(
expected
{
"{}"
,
$expected
}
)
?
,
}
)
)
}};
}
/// Like try_validation, but will throw a validation error if any of the patterns in $p are
...
...
@@ -51,7 +51,7 @@
/// as a kind of validation blacklist:
///
/// ```
/// let v = try_validation
_pat
!(some_fn(), some_path, {
/// let v = try_validation!(some_fn(), some_path, {
/// Foo | Bar | Baz => { "some failure" },
/// });
/// // Failures that match $p are thrown up as validation errors, but other errors are passed back
...
...
@@ -61,7 +61,7 @@
/// An additional expected parameter can also be added to the failure message:
///
/// ```
/// let v = try_validation
_pat
!(some_fn(), some_path, {
/// let v = try_validation!(some_fn(), some_path, {
/// Foo | Bar | Baz => { "some failure" } expected { "something that wasn't a failure" },
/// });
/// ```
...
...
@@ -70,14 +70,15 @@
/// the format string in directly:
///
/// ```
/// let v = try_validation
_pat
!(some_fn(), some_path, {
/// let v = try_validation!(some_fn(), some_path, {
/// Foo | Bar | Baz => { "{:?}", some_failure } expected { "{}", expected_value },
/// });
/// ```
///
macro_rules!
try_validation_pat
{
(
$e:expr
,
$where:expr
,
{
$
(
$p:pat
)|
+
=>
{
$
(
$what_fmt:expr
),
+
}
$
(
expected
{
$
(
$expected_fmt:expr
),
+
}
)
?
$
(
,
)
?
})
=>
{{
macro_rules!
try_validation
{
(
$e:expr
,
$where:expr
,
$
(
$p:pat
)|
+
=>
{
$
(
$what_fmt:expr
),
+
}
$
(
expected
{
$
(
$expected_fmt:expr
),
+
}
)
?
$
(
,
)
?
)
=>
{{
match
$e
{
Ok
(
x
)
=>
x
,
// We catch the error and turn it into a validation failure. We are okay with
...
...
@@ -303,21 +304,28 @@ fn check_wide_ptr_meta(
match
tail
.kind
{
ty
::
Dynamic
(
..
)
=>
{
let
vtable
=
meta
.unwrap_meta
();
// Direct call to `check_ptr_access_align` checks alignment even on CTFE machines.
try_validation!
(
self
.ecx.memory
.check_ptr_access
(
self
.ecx.memory
.check_ptr_access
_align
(
vtable
,
3
*
self
.ecx.tcx.data_layout.pointer_size
,
// drop, size, align
self
.ecx.tcx.data_layout.pointer_align.abi
,
Some
(
self
.ecx.tcx.data_layout.pointer_align.abi
),
CheckInAllocMsg
::
InboundsTest
,
),
"dangling or unaligned vtable pointer in wide pointer or too small vtable"
,
self
.path
self
.path
,
err_ub!
(
PointerOutOfBounds
{
..
})
|
err_ub!
(
AlignmentCheckFailed
{
..
})
|
err_ub!
(
DanglingIntPointer
(
..
))
|
err_unsup!
(
ReadBytesAsPointer
)
=>
{
"dangling or unaligned vtable pointer in wide pointer or too small vtable"
},
);
try_validation!
(
try_validation
_catchall
!
(
self
.ecx
.read_drop_type_from_vtable
(
vtable
),
"invalid drop fn in vtable"
,
self
.path
);
try_validation!
(
try_validation
_catchall
!
(
self
.ecx
.read_size_and_align_from_vtable
(
vtable
),
"invalid size or align in vtable"
,
self
.path
...
...
@@ -327,8 +335,8 @@ fn check_wide_ptr_meta(
ty
::
Slice
(
..
)
|
ty
::
Str
=>
{
let
_
len
=
try_validation!
(
meta
.unwrap_meta
()
.to_machine_usize
(
self
.ecx
),
"non-integer slice length in wide pointer"
,
self
.path
self
.path
,
err_unsup!
(
ReadPointerAsBytes
)
=>
{
"non-integer slice length in wide pointer"
},
);
// We do not check that `len * elem_size <= isize::MAX`:
// that is only required for references, and there it falls out of the
...
...
@@ -354,8 +362,8 @@ fn check_safe_pointer(
// Check metadata early, for better diagnostics
let
place
=
try_validation!
(
self
.ecx
.ref_to_mplace
(
value
),
format_args!
(
"uninitialized {}"
,
kind
)
,
self
.path
self
.path
,
err_ub!
(
InvalidUndefBytes
(
..
))
=>
{
"uninitialized {}"
,
kind
},
);
if
place
.layout
.is_unsized
()
{
self
.check_wide_ptr_meta
(
place
.meta
,
place
.layout
)
?
;
...
...
@@ -376,6 +384,7 @@ fn check_safe_pointer(
// alignment and size determined by the layout (size will be 0,
// alignment should take attributes into account).
.unwrap_or_else
(||
(
place
.layout.size
,
place
.layout.align.abi
));
// Direct call to `check_ptr_access_align` checks alignment even on CTFE machines.
let
ptr
:
Option
<
_
>
=
match
self
.ecx.memory
.check_ptr_access_align
(
place
.ptr
,
size
,
...
...
@@ -489,12 +498,20 @@ fn try_visit_primitive(
match
ty
.kind
{
ty
::
Bool
=>
{
let
value
=
self
.ecx
.read_scalar
(
value
)
?
;
try_validation!
(
value
.to_bool
(),
value
,
self
.path
,
"a boolean"
);
try_validation!
(
value
.to_bool
(),
self
.path
,
err_ub!
(
InvalidBool
(
..
))
=>
{
"{}"
,
value
}
expected
{
"a boolean"
},
);
Ok
(
true
)
}
ty
::
Char
=>
{
let
value
=
self
.ecx
.read_scalar
(
value
)
?
;
try_validation!
(
value
.to_char
(),
value
,
self
.path
,
"a valid unicode codepoint"
);
try_validation!
(
value
.to_char
(),
self
.path
,
err_ub!
(
InvalidChar
(
..
))
=>
{
"{}"
,
value
}
expected
{
"a valid unicode codepoint"
},
);
Ok
(
true
)
}
ty
::
Float
(
_
)
|
ty
::
Int
(
_
)
|
ty
::
Uint
(
_
)
=>
{
...
...
@@ -521,9 +538,11 @@ fn try_visit_primitive(
// We are conservative with undef for integers, but try to
// actually enforce the strict rules for raw pointers (mostly because
// that lets us re-use `ref_to_mplace`).
let
place
=
try_validation_pat!
(
self
.ecx
.ref_to_mplace
(
self
.ecx
.read_immediate
(
value
)
?
),
self
.path
,
{
let
place
=
try_validation!
(
self
.ecx
.ref_to_mplace
(
self
.ecx
.read_immediate
(
value
)
?
),
self
.path
,
err_ub!
(
InvalidUndefBytes
(
..
))
=>
{
"uninitialized raw pointer"
},
}
);
);
if
place
.layout
.is_unsized
()
{
self
.check_wide_ptr_meta
(
place
.meta
,
place
.layout
)
?
;
}
...
...
@@ -539,7 +558,7 @@ fn try_visit_primitive(
}
ty
::
FnPtr
(
_
sig
)
=>
{
let
value
=
self
.ecx
.read_scalar
(
value
)
?
;
let
_
fn
=
try_validation!
(
let
_
fn
=
try_validation
_catchall
!
(
value
.not_undef
()
.and_then
(|
ptr
|
self
.ecx.memory
.get_fn
(
ptr
)),
value
,
self
.path
,
...
...
@@ -598,9 +617,9 @@ fn visit_scalar(
// At least one value is excluded. Get the bits.
let
value
=
try_validation!
(
value
.not_undef
(),
value
,
self
.path
,
format_args!
(
"something {}"
,
wrapping_range_format
(
valid_range
,
max_hi
),)
err_ub!
(
InvalidUndefBytes
(
..
))
=>
{
"{}"
,
value
}
expected
{
"something {}"
,
wrapping_range_format
(
valid_range
,
max_hi
)
},
);
let
bits
=
match
value
.to_bits_or_ptr
(
op
.layout.size
,
self
.ecx
)
{
Err
(
ptr
)
=>
{
...
...
@@ -761,8 +780,8 @@ fn visit_aggregate(
let
mplace
=
op
.assert_mem_place
(
self
.ecx
);
// strings are never immediate
try_validation!
(
self
.ecx
.read_str
(
mplace
),
"uninitialized or non-UTF-8 data in str"
,
self
.path
self
.path
,
err_ub!
(
InvalidStr
(
..
))
=>
{
"uninitialized or non-UTF-8 data in str"
},
);
}
ty
::
Array
(
tys
,
..
)
|
ty
::
Slice
(
tys
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录