Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
744780e7
R
Rust
项目概览
int
/
Rust
大约 1 年 前同步成功
通知
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,发现更多精彩内容 >>
提交
744780e7
编写于
7月 24, 2017
作者:
R
Ralf Jung
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
more hacks to make test cases pass
上级
e2d80d04
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
60 addition
and
23 deletion
+60
-23
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/memory.rs
+4
-2
src/librustc_mir/interpret/validation.rs
src/librustc_mir/interpret/validation.rs
+55
-21
tests/run-pass/cast-rfc0401-vtable-kinds.rs
tests/run-pass/cast-rfc0401-vtable-kinds.rs
+1
-0
未找到文件。
src/librustc_mir/interpret/memory.rs
浏览文件 @
744780e7
...
...
@@ -565,7 +565,7 @@ pub(crate) fn acquire_lock(&mut self, ptr: MemoryPointer, len: u64, region: Opti
Ok
(())
}
/// Release a write lock prematurely. If there's
just read locks, do nothing
.
/// Release a write lock prematurely. If there's
a read lock or someone else's lock, fail
.
pub
(
crate
)
fn
release_write_lock
(
&
mut
self
,
ptr
:
MemoryPointer
,
len
:
u64
)
->
EvalResult
<
'tcx
>
{
assert
!
(
len
>
0
);
let
cur_frame
=
self
.cur_frame
;
...
...
@@ -580,18 +580,20 @@ pub(crate) fn release_write_lock(&mut self, ptr: MemoryPointer, len: u64) -> Eva
return
Err
(
EvalError
::
InvalidMemoryLockRelease
{
ptr
,
len
,
frame
:
cur_frame
,
lock
:
lock
.clone
()
});
}
if
!
range
.contained_in
(
ptr
.offset
,
len
)
{
return
Err
(
EvalError
::
Unimplemented
(
format!
(
"miri does not support releas
e
part of a write-locked region"
)));
return
Err
(
EvalError
::
Unimplemented
(
format!
(
"miri does not support releas
ing
part of a write-locked region"
)));
}
// Release it later. We cannot do this now.
remove_list
.push
(
*
range
);
}
ReadLock
(
_
)
=>
{
// Abort here and bubble the error outwards so that we do not even register a suspension.
return
Err
(
EvalError
::
InvalidMemoryLockRelease
{
ptr
,
len
,
frame
:
cur_frame
,
lock
:
lock
.clone
()
});
},
}
}
for
range
in
remove_list
{
trace!
(
"Releasing {:?}"
,
alloc
.locks
[
&
range
]);
alloc
.locks
.remove
(
&
range
);
}
...
...
src/librustc_mir/interpret/validation.rs
浏览文件 @
744780e7
...
...
@@ -9,8 +9,8 @@
use
error
::{
EvalError
,
EvalResult
};
use
eval_context
::{
EvalContext
,
DynamicLifetime
};
use
memory
::
AccessKind
;
use
value
::
Value
;
use
memory
::
{
AccessKind
,
LockInfo
}
;
use
value
::
{
PrimVal
,
Value
}
;
use
lvalue
::{
Lvalue
,
LvalueExtra
};
pub
type
ValidationQuery
<
'tcx
>
=
ValidationOperand
<
'tcx
,
Lvalue
<
'tcx
>>
;
...
...
@@ -36,8 +36,7 @@ fn acquiring(self) -> bool {
// Validity checks
impl
<
'a
,
'tcx
>
EvalContext
<
'a
,
'tcx
>
{
pub
(
crate
)
fn
validation_op
(
&
mut
self
,
op
:
ValidationOp
,
operand
:
&
ValidationOperand
<
'tcx
,
mir
::
Lvalue
<
'tcx
>>
)
->
EvalResult
<
'tcx
>
{
// Determine if this method is whitelisted and hence we do not perform any validation.
// TODO: Do not do this.
// HACK: Determine if this method is whitelisted and hence we do not perform any validation.
{
// The regexp we use for filtering
use
regex
::
Regex
;
...
...
@@ -46,6 +45,7 @@ pub(crate) fn validation_op(&mut self, op: ValidationOp, operand: &ValidationOpe
std::mem::swap::|
\
std::mem::uninitialized::|
\
std::ptr::read::|
\
std::panicking::try::do_call::|
\
<std::vec::Vec<T>><[a-zA-Z0-9_]+>::into_boxed_slice$
\
)"
)
.unwrap
();
}
...
...
@@ -64,18 +64,30 @@ pub(crate) fn validation_op(&mut self, op: ValidationOp, operand: &ValidationOpe
let
mode
=
match
op
{
ValidationOp
::
Acquire
=>
ValidationMode
::
Acquire
,
ValidationOp
::
Release
=>
ValidationMode
::
Release
,
ValidationOp
::
Suspend
(
_
)
=>
ValidationMode
::
Release
,
};
match
self
.validate
(
query
.clone
(),
mode
)
{
Err
(
EvalError
::
InvalidMemoryLockRelease
{
lock
:
LockInfo
::
ReadLock
(
_
),
..
})
=>
{
// HACK: When &x is used while x is already borrowed read-only, AddValidation still
// emits suspension. This code is legit, so just ignore the error *and*
// do NOT register a suspension.
// TODO: Integrate AddValidation better with borrowck so that we can/ not emit
// these wrong validation statements. This is all pretty fragile right now.
return
Ok
(());
}
res
=>
res
,
}
?
;
// Now that we are here, we know things went well. Time to register the suspension.
match
op
{
ValidationOp
::
Suspend
(
ce
)
=>
{
if
operand
.mutbl
==
MutImmutable
{
// Nothing to do when suspending immutable things
return
Ok
(());
if
query
.mutbl
==
MutMutable
{
let
lft
=
DynamicLifetime
{
frame
:
self
.cur_frame
(),
region
:
Some
(
ce
)
};
trace!
(
"Suspending {:?} until {:?}"
,
query
,
ce
);
self
.suspended
.entry
(
lft
)
.or_insert_with
(
Vec
::
new
)
.push
(
query
);
}
let
lft
=
DynamicLifetime
{
frame
:
self
.cur_frame
(),
region
:
Some
(
ce
)
};
trace!
(
"Suspending {:?} until {:?}"
,
query
,
ce
);
self
.suspended
.entry
(
lft
)
.or_insert_with
(
Vec
::
new
)
.push
(
query
.clone
());
ValidationMode
::
Release
}
_
=>
{}
};
self
.validate
(
query
,
mode
)
?
;
Ok
(())
}
...
...
@@ -85,6 +97,7 @@ pub(crate) fn end_region(&mut self, ce: CodeExtent) -> EvalResult<'tcx> {
let
lft
=
DynamicLifetime
{
frame
:
self
.cur_frame
(),
region
:
Some
(
ce
)
};
if
let
Some
(
queries
)
=
self
.suspended
.remove
(
&
lft
)
{
for
query
in
queries
{
trace!
(
"Recovering {:?} from suspension"
,
query
);
self
.validate
(
query
,
ValidationMode
::
Recover
(
ce
))
?
;
}
}
...
...
@@ -111,7 +124,18 @@ fn validate_ptr(&mut self, val: Value, pointee_ty: Ty<'tcx>, re: Option<CodeExte
// Check alignment and non-NULLness
let
(
_
,
align
)
=
self
.size_and_align_of_dst
(
pointee_ty
,
val
)
?
;
let
ptr
=
val
.into_ptr
(
&
mut
self
.memory
)
?
;
self
.memory
.check_align
(
ptr
,
align
)
?
;
match
self
.memory
.check_align
(
ptr
,
align
)
{
// HACK: If, during releasing, we hit memory we cannot use, we just ignore that.
// This can happen because releases are added before drop elaboration.
// TODO: Fix the MIR so that these releases do not happen.
res
@
Err
(
EvalError
::
DanglingPointerDeref
)
|
res
@
Err
(
EvalError
::
ReadUndefBytes
)
=>
{
if
let
ValidationMode
::
Release
=
mode
{
return
Ok
(());
}
res
}
res
=>
res
,
}
?
;
// Recurse
let
pointee_lvalue
=
self
.val_to_lvalue
(
val
,
pointee_ty
)
?
;
...
...
@@ -136,14 +160,24 @@ fn validate(&mut self, mut query: ValidationQuery<'tcx>, mode: ValidationMode) -
}
}
// For now, bail out if we hit a dead local.
// TODO: Reconsider this. I think MIR should rather be fixed.
// HACK: For now, bail out if we hit a dead local during recovery (can happen because sometimes we have
// StorageDead before EndRegion).
// TODO: We should rather fix the MIR.
// HACK: Releasing on dead/undef local variables is a NOP. This can happen because of releases being added
// before drop elaboration.
// TODO: Fix the MIR so that these releases do not happen.
match
query
.lval
{
Lvalue
::
Local
{
frame
,
local
}
=>
{
if
let
Err
(
EvalError
::
DeadLocal
)
=
self
.stack
[
frame
]
.get_local
(
local
)
{
return
Ok
(())
let
res
=
self
.stack
[
frame
]
.get_local
(
local
);
match
(
res
,
mode
)
{
(
Err
(
EvalError
::
DeadLocal
),
ValidationMode
::
Recover
(
_
))
|
(
Err
(
EvalError
::
DeadLocal
),
ValidationMode
::
Release
)
|
(
Ok
(
Value
::
ByVal
(
PrimVal
::
Undef
)),
ValidationMode
::
Release
)
=>
{
return
Ok
(());
}
_
=>
{},
}
}
}
,
_
=>
{}
}
...
...
@@ -229,7 +263,7 @@ fn validate(&mut self, mut query: ValidationQuery<'tcx>, mode: ValidationMode) -
if
query
.re
==
None
{
match
*
region
{
ReScope
(
ce
)
=>
query
.re
=
Some
(
ce
),
// It is possible for us to enco
de
erased lifetimes here because the lifetimes in
// It is possible for us to enco
unter
erased lifetimes here because the lifetimes in
// this functions' Subst will be erased.
_
=>
{},
}
...
...
@@ -279,10 +313,10 @@ fn validate(&mut self, mut query: ValidationQuery<'tcx>, mode: ValidationMode) -
};
self
.read_size_and_align_from_vtable
(
vtable
)
?
;
// TODO: Check that the vtable contains all the function pointers we expect it to have.
// T
ODO: Is there anything we can/should validate here? T
rait objects cannot have any operations performed
// Trait objects cannot have any operations performed
// on them directly. We cannot, in general, even acquire any locks as the trait object *could*
// contain an UnsafeCell. If we call functions to get access to data, we will validate
// their return values. So, it doesn't seem like there's anything to do.
// their return values. So, it doesn't seem like there's anything
else
to do.
Ok
(())
}
TyAdt
(
adt
,
subst
)
=>
{
...
...
tests/run-pass/cast-rfc0401-vtable-kinds.rs
浏览文件 @
744780e7
...
...
@@ -55,4 +55,5 @@ fn main() {
let
bar_ref
:
*
const
BarS
<
[
u32
]
>
=
foo_to_bar
(
u
);
let
z
:
&
BarS
<
[
u32
]
>
=
unsafe
{
&*
bar_ref
};
assert_eq!
(
&
z
.0
,
&
[
0
,
1
,
2
]);
// If validation fails here, that's likely because an immutable suspension is recovered mutably.
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录