diff --git a/src/Magnum/Trade/SceneData.cpp b/src/Magnum/Trade/SceneData.cpp index a27fd23df..d2f7f8ee1 100644 --- a/src/Magnum/Trade/SceneData.cpp +++ b/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(fieldData.data())) < (1ll << 47), + "Trade::SceneFieldData: (signed) distance between string data and field data expected to fit into 48 bits but got" << static_cast(stringData) << "and" << fieldData.data(), ); + #endif } SceneFieldData::SceneFieldData(const SceneField name, const Containers::StridedArrayView2D& mappingData, const char* const stringData, const SceneFieldType fieldType, const Containers::StridedArrayView2D& fieldData, const SceneFieldFlags flags) noexcept: SceneFieldData{name, {}, Containers::StridedArrayView1D{{mappingData.data(), ~std::size_t{}}, mappingData.size()[0], mappingData.stride()[0]}, stringData, fieldType, Containers::StridedArrayView1D{{fieldData.data(), ~std::size_t{}}, fieldData.size()[0], fieldData.stride()[0]}, flags} { diff --git a/src/Magnum/Trade/SceneData.h b/src/Magnum/Trade/SceneData.h index 7aad7f3bc..8eaf31cde 100644 --- a/src/Magnum/Trade/SceneData.h +++ b/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 Containers::StridedArrayView1D SceneData::mapping(const UnsignedInt fieldId) const { diff --git a/src/Magnum/Trade/Test/SceneDataTest.cpp b/src/Magnum/Trade/Test/SceneDataTest.cpp index 855c9cb3f..a397598c9 100644 --- a/src/Magnum/Trade/Test/SceneDataTest.cpp +++ b/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(0xfeedbeefull), SceneFieldType::StringOffset8, + Containers::arrayView(reinterpret_cast(0x8000feedbeefull), 3)}; + SceneFieldData{sceneFieldCustom(166), + Containers::arrayView(mappingData), + reinterpret_cast(0x8000feedbeefull), SceneFieldType::StringOffset8, + Containers::arrayView(reinterpret_cast(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;