mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-08-04 03:05:42 +00:00
tint: Fix C++ UB when shifting abstract 0 left by >= 64
In WGSL, we can shift left abstracts by >= 64, as long as the result is representable in the data type we choose for it. When shifting 0, we can shift by any positive u32 value (result is always 0), but in C++, it's UB to shift by more than the bit width of the data type, so we need to handle this. This bug was caught by ClusterFuzz. Bug: chromium:1372963 Change-Id: I638ca190b93538908ca6472f3735627ea8531c5a Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/106266 Reviewed-by: David Neto <dneto@google.com> Commit-Queue: Antonio Maiorano <amaiorano@google.com> Reviewed-by: Dan Sinclair <dsinclair@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
e4d608a837
commit
b6e1bc7d5d
@ -1474,6 +1474,10 @@ ConstEval::Result ConstEval::OpShiftLeft(const sem::Type* ty,
|
||||
AddError(OverflowErrorMessage(e1, "<<", e2), source);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// It's UB in C++ to shift by greater or equal to the bit width (even if the lhs
|
||||
// is 0), so we make sure to avoid this by setting the shift value to 0.
|
||||
e2 = 0;
|
||||
}
|
||||
} else {
|
||||
if (static_cast<size_t>(e2) >= bit_width) {
|
||||
|
@ -598,7 +598,7 @@ std::vector<Case> ShiftLeftCases() {
|
||||
// Shift type is u32 for non-abstract
|
||||
using ST = std::conditional_t<IsAbstract<T>, T, u32>;
|
||||
using B = BitValues<T>;
|
||||
return {
|
||||
auto r = std::vector<Case>{
|
||||
C(T{0b1010}, ST{0}, T{0b0000'0000'1010}), //
|
||||
C(T{0b1010}, ST{1}, T{0b0000'0001'0100}), //
|
||||
C(T{0b1010}, ST{2}, T{0b0000'0010'1000}), //
|
||||
@ -626,6 +626,25 @@ std::vector<Case> ShiftLeftCases() {
|
||||
Vec(ST{6}, ST{7}, ST{8}), //
|
||||
Vec(T{0b0010'1000'0000}, T{0b0101'0000'0000}, T{0b1010'0000'0000})), //
|
||||
};
|
||||
|
||||
// Only abstract 0 can be shifted left as much as we like. For concrete 0 (and any number), it
|
||||
// cannot be shifted equal or more than the number of bits of the lhs (see
|
||||
// ResolverConstEvalShiftLeftConcreteGeqBitWidthError)
|
||||
ConcatIntoIf<IsAbstract<T>>( //
|
||||
r, std::vector<Case>{
|
||||
C(T{0}, ST{64}, T{0}),
|
||||
C(T{0}, ST{65}, T{0}),
|
||||
C(T{0}, ST{65}, T{0}),
|
||||
C(T{0}, ST{10000}, T{0}),
|
||||
C(T{0}, T::Highest(), T{0}),
|
||||
C(Negate(T{0}), ST{64}, Negate(T{0})),
|
||||
C(Negate(T{0}), ST{65}, Negate(T{0})),
|
||||
C(Negate(T{0}), ST{65}, Negate(T{0})),
|
||||
C(Negate(T{0}), ST{10000}, Negate(T{0})),
|
||||
C(Negate(T{0}), T::Highest(), Negate(T{0})),
|
||||
});
|
||||
|
||||
return r;
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(ShiftLeft,
|
||||
ResolverConstEvalBinaryOpTest,
|
||||
@ -850,15 +869,37 @@ TEST_P(ResolverConstEvalShiftLeftConcreteGeqBitWidthError, Test) {
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(Test,
|
||||
ResolverConstEvalShiftLeftConcreteGeqBitWidthError,
|
||||
testing::Values( //
|
||||
std::make_tuple(Val(1_i), Val(32_u)), //
|
||||
std::make_tuple(Val(1_i), Val(33_u)), //
|
||||
std::make_tuple(Val(1_i), Val(34_u)), //
|
||||
std::make_tuple(Val(1_i), Val(99999999_u)), //
|
||||
std::make_tuple(Val(1_u), Val(32_u)), //
|
||||
std::make_tuple(Val(1_u), Val(33_u)), //
|
||||
std::make_tuple(Val(1_u), Val(34_u)), //
|
||||
std::make_tuple(Val(1_u), Val(99999999_u)) //
|
||||
testing::Values( //
|
||||
std::make_tuple(Val(0_u), Val(32_u)), //
|
||||
std::make_tuple(Val(0_u), Val(33_u)), //
|
||||
std::make_tuple(Val(0_u), Val(34_u)), //
|
||||
std::make_tuple(Val(0_u), Val(10000_u)), //
|
||||
std::make_tuple(Val(0_u), Val(u32::Highest())), //
|
||||
std::make_tuple(Val(0_i), Val(32_u)), //
|
||||
std::make_tuple(Val(0_i), Val(33_u)), //
|
||||
std::make_tuple(Val(0_i), Val(34_u)), //
|
||||
std::make_tuple(Val(0_i), Val(10000_u)), //
|
||||
std::make_tuple(Val(0_i), Val(u32::Highest())), //
|
||||
std::make_tuple(Val(Negate(0_u)), Val(32_u)), //
|
||||
std::make_tuple(Val(Negate(0_u)), Val(33_u)), //
|
||||
std::make_tuple(Val(Negate(0_u)), Val(34_u)), //
|
||||
std::make_tuple(Val(Negate(0_u)), Val(10000_u)), //
|
||||
std::make_tuple(Val(Negate(0_u)), Val(u32::Highest())), //
|
||||
std::make_tuple(Val(Negate(0_i)), Val(32_u)), //
|
||||
std::make_tuple(Val(Negate(0_i)), Val(33_u)), //
|
||||
std::make_tuple(Val(Negate(0_i)), Val(34_u)), //
|
||||
std::make_tuple(Val(Negate(0_i)), Val(10000_u)), //
|
||||
std::make_tuple(Val(Negate(0_i)), Val(u32::Highest())), //
|
||||
std::make_tuple(Val(1_i), Val(32_u)), //
|
||||
std::make_tuple(Val(1_i), Val(33_u)), //
|
||||
std::make_tuple(Val(1_i), Val(34_u)), //
|
||||
std::make_tuple(Val(1_i), Val(10000_u)), //
|
||||
std::make_tuple(Val(1_i), Val(u32::Highest())), //
|
||||
std::make_tuple(Val(1_u), Val(32_u)), //
|
||||
std::make_tuple(Val(1_u), Val(33_u)), //
|
||||
std::make_tuple(Val(1_u), Val(34_u)), //
|
||||
std::make_tuple(Val(1_u), Val(10000_u)), //
|
||||
std::make_tuple(Val(1_u), Val(u32::Highest())) //
|
||||
));
|
||||
|
||||
// AInt left shift results in sign change error
|
||||
|
8
test/tint/bug/chromium/1372963.wgsl
Normal file
8
test/tint/bug/chromium/1372963.wgsl
Normal file
@ -0,0 +1,8 @@
|
||||
fn g() -> vec4<i32> {
|
||||
return vec4(-0) << vec4(2147483649);
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn main() {
|
||||
g();
|
||||
}
|
8
test/tint/bug/chromium/1372963.wgsl.expected.dxc.hlsl
Normal file
8
test/tint/bug/chromium/1372963.wgsl.expected.dxc.hlsl
Normal file
@ -0,0 +1,8 @@
|
||||
int4 g() {
|
||||
return (0).xxxx;
|
||||
}
|
||||
|
||||
void main() {
|
||||
g();
|
||||
return;
|
||||
}
|
8
test/tint/bug/chromium/1372963.wgsl.expected.fxc.hlsl
Normal file
8
test/tint/bug/chromium/1372963.wgsl.expected.fxc.hlsl
Normal file
@ -0,0 +1,8 @@
|
||||
int4 g() {
|
||||
return (0).xxxx;
|
||||
}
|
||||
|
||||
void main() {
|
||||
g();
|
||||
return;
|
||||
}
|
15
test/tint/bug/chromium/1372963.wgsl.expected.glsl
Normal file
15
test/tint/bug/chromium/1372963.wgsl.expected.glsl
Normal file
@ -0,0 +1,15 @@
|
||||
#version 310 es
|
||||
precision mediump float;
|
||||
|
||||
ivec4 g() {
|
||||
return ivec4(0);
|
||||
}
|
||||
|
||||
void tint_symbol() {
|
||||
g();
|
||||
}
|
||||
|
||||
void main() {
|
||||
tint_symbol();
|
||||
return;
|
||||
}
|
12
test/tint/bug/chromium/1372963.wgsl.expected.msl
Normal file
12
test/tint/bug/chromium/1372963.wgsl.expected.msl
Normal file
@ -0,0 +1,12 @@
|
||||
#include <metal_stdlib>
|
||||
|
||||
using namespace metal;
|
||||
int4 g() {
|
||||
return int4(0);
|
||||
}
|
||||
|
||||
fragment void tint_symbol() {
|
||||
g();
|
||||
return;
|
||||
}
|
||||
|
26
test/tint/bug/chromium/1372963.wgsl.expected.spvasm
Normal file
26
test/tint/bug/chromium/1372963.wgsl.expected.spvasm
Normal file
@ -0,0 +1,26 @@
|
||||
; SPIR-V
|
||||
; Version: 1.3
|
||||
; Generator: Google Tint Compiler; 0
|
||||
; Bound: 12
|
||||
; Schema: 0
|
||||
OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpName %g "g"
|
||||
OpName %main "main"
|
||||
%int = OpTypeInt 32 1
|
||||
%v4int = OpTypeVector %int 4
|
||||
%1 = OpTypeFunction %v4int
|
||||
%6 = OpConstantNull %v4int
|
||||
%void = OpTypeVoid
|
||||
%7 = OpTypeFunction %void
|
||||
%g = OpFunction %v4int None %1
|
||||
%5 = OpLabel
|
||||
OpReturnValue %6
|
||||
OpFunctionEnd
|
||||
%main = OpFunction %void None %7
|
||||
%10 = OpLabel
|
||||
%11 = OpFunctionCall %v4int %g
|
||||
OpReturn
|
||||
OpFunctionEnd
|
8
test/tint/bug/chromium/1372963.wgsl.expected.wgsl
Normal file
8
test/tint/bug/chromium/1372963.wgsl.expected.wgsl
Normal file
@ -0,0 +1,8 @@
|
||||
fn g() -> vec4<i32> {
|
||||
return (vec4(0) << vec4(2147483649));
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn main() {
|
||||
g();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user