Browse Source

Trade: assertions for string data being too far apart on 64 bits.

I'm seeing an assert for null string data not being correctly thrown in
a SceneTools API on ARM64 and an overflow of this 48-bit offset seems to
be a culprit. So better have that covered in the constructor already.
pull/620/head
Vladimír Vondruš 3 years ago
parent
commit
cc0db3dd08
  1. 5
      src/Magnum/Trade/SceneData.cpp
  2. 8
      src/Magnum/Trade/SceneData.h
  3. 32
      src/Magnum/Trade/Test/SceneDataTest.cpp

5
src/Magnum/Trade/SceneData.cpp

@ -647,6 +647,11 @@ SceneFieldData::SceneFieldData(const SceneField name, const SceneMappingType map
"Trade::SceneFieldData: expected mapping view stride to fit into 16 bits but got" << mappingData.stride(), );
CORRADE_ASSERT(fieldData.stride() >= -32768 && fieldData.stride() <= 32767,
"Trade::SceneFieldData: expected field view stride to fit into 16 bits but got" << fieldData.stride(), );
#ifndef CORRADE_TARGET_32BIT
/* 47 because the distance is signed */
CORRADE_ASSERT(Utility::abs(stringData - static_cast<const char*>(fieldData.data())) < (1ll << 47),
"Trade::SceneFieldData: (signed) distance between string data and field data expected to fit into 48 bits but got" << static_cast<const void*>(stringData) << "and" << fieldData.data(), );
#endif
}
SceneFieldData::SceneFieldData(const SceneField name, const Containers::StridedArrayView2D<const char>& mappingData, const char* const stringData, const SceneFieldType fieldType, const Containers::StridedArrayView2D<const char>& fieldData, const SceneFieldFlags flags) noexcept: SceneFieldData{name, {}, Containers::StridedArrayView1D<const void>{{mappingData.data(), ~std::size_t{}}, mappingData.size()[0], mappingData.stride()[0]}, stringData, fieldType, Containers::StridedArrayView1D<const void>{{fieldData.data(), ~std::size_t{}}, fieldData.size()[0], fieldData.stride()[0]}, flags} {

8
src/Magnum/Trade/SceneData.h

@ -4158,7 +4158,13 @@ constexpr SceneFieldData::SceneFieldData(const SceneField name, const std::size_
_field{
(CORRADE_CONSTEXPR_ASSERT(fieldStride >= -32768 && fieldStride <= 32767,
"Trade::SceneFieldData: expected field view stride to fit into 16 bits but got" << fieldStride), Short(fieldStride)),
Long(stringOffset)},
(
#ifndef CORRADE_TARGET_32BIT
/* 47 because the distance is signed */
CORRADE_CONSTEXPR_ASSERT(stringOffset < (1ull << 47),
"Trade::SceneFieldData: expected string data offset to fit into 48 bits but got" << stringOffset),
#endif
Long(stringOffset))},
_fieldData{fieldOffset} {}
template<class T> Containers::StridedArrayView1D<const T> SceneData::mapping(const UnsignedInt fieldId) const {

32
src/Magnum/Trade/Test/SceneDataTest.cpp

@ -127,6 +127,9 @@ struct SceneDataTest: TestSuite::Tester {
void constructFieldArrayTypeErased2DNonContiguous();
void constructFieldBitTooLargeBitOffset();
void constructFieldBitTooLargeSize();
#ifndef CORRADE_TARGET_32BIT
void constructFieldStringDataTooFarApart();
#endif
void construct();
void constructZeroFields();
@ -471,6 +474,9 @@ SceneDataTest::SceneDataTest() {
&SceneDataTest::constructFieldArrayTypeErased2DNonContiguous,
&SceneDataTest::constructFieldBitTooLargeBitOffset,
&SceneDataTest::constructFieldBitTooLargeSize,
#ifndef CORRADE_TARGET_32BIT
&SceneDataTest::constructFieldStringDataTooFarApart,
#endif
&SceneDataTest::construct,
&SceneDataTest::constructZeroFields,
@ -2434,6 +2440,32 @@ void SceneDataTest::constructFieldBitTooLargeSize() {
#endif
}
#ifndef CORRADE_TARGET_32BIT
void SceneDataTest::constructFieldStringDataTooFarApart() {
CORRADE_SKIP_IF_NO_ASSERT();
UnsignedShort mappingData[3]{};
std::ostringstream out;
Error redirectError{&out};
SceneFieldData{sceneFieldCustom(166),
Containers::arrayView(mappingData),
reinterpret_cast<const char*>(0xfeedbeefull), SceneFieldType::StringOffset8,
Containers::arrayView(reinterpret_cast<const UnsignedByte*>(0x8000feedbeefull), 3)};
SceneFieldData{sceneFieldCustom(166),
Containers::arrayView(mappingData),
reinterpret_cast<const char*>(0x8000feedbeefull), SceneFieldType::StringOffset8,
Containers::arrayView(reinterpret_cast<const UnsignedByte*>(0xfeedbeefull), 3)};
SceneFieldData{sceneFieldCustom(661), 3,
SceneMappingType::UnsignedShort, 1725676, 2,
0x800000000000ull, SceneFieldType::StringOffset8, 72567654, 8};
CORRADE_COMPARE(out.str(),
"Trade::SceneFieldData: (signed) distance between string data and field data expected to fit into 48 bits but got 0xfeedbeef and 0x8000feedbeef\n"
"Trade::SceneFieldData: (signed) distance between string data and field data expected to fit into 48 bits but got 0x8000feedbeef and 0xfeedbeef\n"
"Trade::SceneFieldData: expected string data offset to fit into 48 bits but got 140737488355328\n");
}
#endif
void SceneDataTest::construct() {
struct TransformParent {
UnsignedShort object;

Loading…
Cancel
Save