Check that stores are permitted by the pointer's storage access.

Fixes #1533.
This commit is contained in:
Jim Blandy
2021-11-15 22:46:00 -08:00
committed by Dzmitry Malyshau
parent 3d6cbcf8a6
commit ce18eba695
5 changed files with 73 additions and 5 deletions

View File

@@ -184,6 +184,21 @@ impl super::TypeInner {
}
}
impl super::StorageClass {
pub fn access(self) -> crate::StorageAccess {
use crate::StorageAccess as Sa;
match self {
crate::StorageClass::Function
| crate::StorageClass::Private
| crate::StorageClass::WorkGroup => Sa::LOAD | Sa::STORE,
crate::StorageClass::Uniform => Sa::LOAD,
crate::StorageClass::Storage { access } => access,
crate::StorageClass::Handle => Sa::LOAD,
crate::StorageClass::PushConstant => Sa::LOAD,
}
}
}
impl super::MathFunction {
pub fn argument_count(&self) -> usize {
match *self {

View File

@@ -606,10 +606,12 @@ impl super::Validator {
}
_ => {}
}
let good = match *context
let pointer_ty = context
.resolve_pointer_type(pointer)
.map_err(|e| e.with_span())?
{
.map_err(|e| e.with_span())?;
let good = match *pointer_ty {
Ti::Pointer { base, class: _ } => match context.types[base].inner {
Ti::Atomic { kind, width } => *value_ty == Ti::Scalar { kind, width },
ref other => value_ty == other,
@@ -634,6 +636,16 @@ impl super::Validator {
.with_handle(pointer, context.expressions)
.with_handle(value, context.expressions));
}
if let Some(class) = pointer_ty.pointer_class() {
if !class.access().contains(crate::StorageAccess::STORE) {
return Err(FunctionError::InvalidStorePointer(pointer)
.with_span_static(
context.expressions.get_span(pointer),
"writing to this location is not permitted",
));
}
}
}
S::ImageStore {
image,

View File

@@ -7,7 +7,7 @@ struct Globals {
m: mat3x4<f32>;
};
[[group(0), binding(0)]] var<storage> globals: Globals;
[[group(0), binding(0)]] var<storage, read_write> globals: Globals;
fn index_array(i: i32) -> f32 {
return globals.a[i];

View File

@@ -14,7 +14,6 @@ OpMemberDecorate %9 1 Offset 48
OpMemberDecorate %9 2 Offset 64
OpMemberDecorate %9 2 ColMajor
OpMemberDecorate %9 2 MatrixStride 16
OpDecorate %10 NonWritable
OpDecorate %10 DescriptorSet 0
OpDecorate %10 Binding 0
%2 = OpTypeVoid

View File

@@ -1029,3 +1029,45 @@ fn missing_default_case() {
)
}
}
#[test]
fn wrong_access_mode() {
// The assignments to `global.i` should be forbidden, because they are in
// variables whose access mode is `read`, not `read_write`.
check_validation_error! {
"
[[block]]
struct Globals {
i: i32;
};
[[group(0), binding(0)]]
var<storage> globals: Globals;
fn store(v: i32) {
globals.i = v;
}
",
"
[[block]]
struct Globals {
i: i32;
};
[[group(0), binding(0)]]
var<uniform> globals: Globals;
fn store(v: i32) {
globals.i = v;
}
":
Err(
naga::valid::ValidationError::Function {
name,
error: naga::valid::FunctionError::InvalidStorePointer(_),
..
},
)
if name == "store"
}
}