mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-03 03:35:59 +00:00
tint: fix insertBits edge case
If count is highest and offset is non-zero, or vice-versa, we'd overflow the count + offset > bit-width check. This CL fixes this case. Also folded in error tests into extractBits and insertBits. Bug: tint:1581 Bug: chromium:53440 Change-Id: Id1e9e737b8076e8075da5992a41d18b6b7c8afd4 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/110482 Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: Antonio Maiorano <amaiorano@google.com> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
99796361ad
commit
8fbfacfd43
@ -2092,19 +2092,19 @@ ConstEval::Result ConstEval::insertBits(const sem::Type* ty,
|
|||||||
NumberUT in_offset = args[2]->As<NumberUT>();
|
NumberUT in_offset = args[2]->As<NumberUT>();
|
||||||
NumberUT in_count = args[3]->As<NumberUT>();
|
NumberUT in_count = args[3]->As<NumberUT>();
|
||||||
|
|
||||||
constexpr UT w = sizeof(UT) * 8;
|
|
||||||
if ((in_offset + in_count) > w) {
|
|
||||||
AddError("'offset + 'count' must be less than or equal to the bit width of 'e'",
|
|
||||||
source);
|
|
||||||
return utils::Failure;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cast all to unsigned
|
// Cast all to unsigned
|
||||||
UT e = static_cast<UT>(in_e);
|
UT e = static_cast<UT>(in_e);
|
||||||
UT newbits = static_cast<UT>(in_newbits);
|
UT newbits = static_cast<UT>(in_newbits);
|
||||||
UT o = static_cast<UT>(in_offset);
|
UT o = static_cast<UT>(in_offset);
|
||||||
UT c = static_cast<UT>(in_count);
|
UT c = static_cast<UT>(in_count);
|
||||||
|
|
||||||
|
constexpr UT w = sizeof(UT) * 8;
|
||||||
|
if (o > w || c > w || (o + c) > w) {
|
||||||
|
AddError("'offset + 'count' must be less than or equal to the bit width of 'e'",
|
||||||
|
source);
|
||||||
|
return utils::Failure;
|
||||||
|
}
|
||||||
|
|
||||||
NumberT result;
|
NumberT result;
|
||||||
if (c == UT{0}) {
|
if (c == UT{0}) {
|
||||||
// The result is e if c is 0
|
// The result is e if c is 0
|
||||||
|
@ -1150,6 +1150,26 @@ std::vector<Case> InsertBitsCases() {
|
|||||||
T(0b1010'0101'1010'0101'1010'0111'1111'1101))),
|
T(0b1010'0101'1010'0101'1010'0111'1111'1101))),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char* error_msg =
|
||||||
|
"12:34 error: 'offset + 'count' must be less than or equal to the bit width of 'e'";
|
||||||
|
ConcatInto( //
|
||||||
|
r, std::vector<Case>{
|
||||||
|
E({T(1), T(1), UT(33), UT(0)}, error_msg), //
|
||||||
|
E({T(1), T(1), UT(34), UT(0)}, error_msg), //
|
||||||
|
E({T(1), T(1), UT(1000), UT(0)}, error_msg), //
|
||||||
|
E({T(1), T(1), UT::Highest(), UT()}, error_msg), //
|
||||||
|
E({T(1), T(1), UT(0), UT(33)}, error_msg), //
|
||||||
|
E({T(1), T(1), UT(0), UT(34)}, error_msg), //
|
||||||
|
E({T(1), T(1), UT(0), UT(1000)}, error_msg), //
|
||||||
|
E({T(1), T(1), UT(0), UT::Highest()}, error_msg), //
|
||||||
|
E({T(1), T(1), UT(33), UT(33)}, error_msg), //
|
||||||
|
E({T(1), T(1), UT(34), UT(34)}, error_msg), //
|
||||||
|
E({T(1), T(1), UT(1000), UT(1000)}, error_msg), //
|
||||||
|
E({T(1), T(1), UT::Highest(), UT(1)}, error_msg),
|
||||||
|
E({T(1), T(1), UT(1), UT::Highest()}, error_msg),
|
||||||
|
E({T(1), T(1), UT::Highest(), u32::Highest()}, error_msg),
|
||||||
|
});
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
INSTANTIATE_TEST_SUITE_P( //
|
INSTANTIATE_TEST_SUITE_P( //
|
||||||
@ -1253,6 +1273,26 @@ std::vector<Case> ExtractBitsCases() {
|
|||||||
set_msbs_if_signed(T(0b11010001)))),
|
set_msbs_if_signed(T(0b11010001)))),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char* error_msg =
|
||||||
|
"12:34 error: 'offset + 'count' must be less than or equal to the bit width of 'e'";
|
||||||
|
ConcatInto( //
|
||||||
|
r, std::vector<Case>{
|
||||||
|
E({T(1), UT(33), UT(0)}, error_msg),
|
||||||
|
E({T(1), UT(34), UT(0)}, error_msg),
|
||||||
|
E({T(1), UT(1000), UT(0)}, error_msg),
|
||||||
|
E({T(1), UT::Highest(), UT(0)}, error_msg),
|
||||||
|
E({T(1), UT(0), UT(33)}, error_msg),
|
||||||
|
E({T(1), UT(0), UT(34)}, error_msg),
|
||||||
|
E({T(1), UT(0), UT(1000)}, error_msg),
|
||||||
|
E({T(1), UT(0), UT::Highest()}, error_msg),
|
||||||
|
E({T(1), UT(33), UT(33)}, error_msg),
|
||||||
|
E({T(1), UT(34), UT(34)}, error_msg),
|
||||||
|
E({T(1), UT(1000), UT(1000)}, error_msg),
|
||||||
|
E({T(1), UT::Highest(), UT(1)}, error_msg),
|
||||||
|
E({T(1), UT(1), UT::Highest()}, error_msg),
|
||||||
|
E({T(1), UT::Highest(), UT::Highest()}, error_msg),
|
||||||
|
});
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
INSTANTIATE_TEST_SUITE_P( //
|
INSTANTIATE_TEST_SUITE_P( //
|
||||||
@ -1262,35 +1302,6 @@ INSTANTIATE_TEST_SUITE_P( //
|
|||||||
testing::ValuesIn(Concat(ExtractBitsCases<i32>(), //
|
testing::ValuesIn(Concat(ExtractBitsCases<i32>(), //
|
||||||
ExtractBitsCases<u32>()))));
|
ExtractBitsCases<u32>()))));
|
||||||
|
|
||||||
using ResolverConstEvalBuiltinTest_ExtractBits_InvalidOffsetAndCount =
|
|
||||||
ResolverTestWithParam<std::tuple<size_t, size_t>>;
|
|
||||||
TEST_P(ResolverConstEvalBuiltinTest_ExtractBits_InvalidOffsetAndCount, Test) {
|
|
||||||
auto& p = GetParam();
|
|
||||||
auto* expr = Call(Source{{12, 34}}, sem::str(sem::BuiltinType::kExtractBits), Expr(1_u),
|
|
||||||
Expr(u32(std::get<0>(p))), Expr(u32(std::get<1>(p))));
|
|
||||||
GlobalConst("C", expr);
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
|
||||||
EXPECT_EQ(r()->error(),
|
|
||||||
"12:34 error: 'offset + 'count' must be less than or equal to the bit width of 'e'");
|
|
||||||
}
|
|
||||||
INSTANTIATE_TEST_SUITE_P(ExtractBits,
|
|
||||||
ResolverConstEvalBuiltinTest_ExtractBits_InvalidOffsetAndCount,
|
|
||||||
testing::Values( //
|
|
||||||
std::make_tuple(33, 0), //
|
|
||||||
std::make_tuple(34, 0), //
|
|
||||||
std::make_tuple(1000, 0), //
|
|
||||||
std::make_tuple(u32::Highest(), 0), //
|
|
||||||
std::make_tuple(0, 33), //
|
|
||||||
std::make_tuple(0, 34), //
|
|
||||||
std::make_tuple(0, 1000), //
|
|
||||||
std::make_tuple(0, u32::Highest()), //
|
|
||||||
std::make_tuple(33, 33), //
|
|
||||||
std::make_tuple(34, 34), //
|
|
||||||
std::make_tuple(1000, 1000), //
|
|
||||||
std::make_tuple(u32::Highest(), 1), //
|
|
||||||
std::make_tuple(1, u32::Highest()), //
|
|
||||||
std::make_tuple(u32::Highest(), u32::Highest())));
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::vector<Case> MaxCases() {
|
std::vector<Case> MaxCases() {
|
||||||
return {
|
return {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user