Browse Source

Trade: disallow empty MaterialAttributeData names.

Overlooked during the initial design -- it'd sort before " LayerName",
which is undesirable.
pull/542/merge
Vladimír Vondruš 4 years ago
parent
commit
e08efa62a1
  1. 3
      src/Magnum/Trade/MaterialData.cpp
  2. 16
      src/Magnum/Trade/MaterialData.h
  3. 40
      src/Magnum/Trade/Test/MaterialDataTest.cpp

3
src/Magnum/Trade/MaterialData.cpp

@ -130,6 +130,9 @@ std::size_t materialAttributeTypeSize(const MaterialAttributeType type) {
} }
MaterialAttributeData::MaterialAttributeData(const Containers::StringView name, const MaterialAttributeType type, const std::size_t size, const void* const value) noexcept: _data{} /* zero-initialized */ { MaterialAttributeData::MaterialAttributeData(const Containers::StringView name, const MaterialAttributeType type, const std::size_t size, const void* const value) noexcept: _data{} /* zero-initialized */ {
/* It would sort before " LayerName" and that's not desirable */
CORRADE_ASSERT(!name.isEmpty(), "Trade::MaterialAttributeData: name is not allowed to be empty", );
/* Special handling for strings */ /* Special handling for strings */
if(type == MaterialAttributeType::String) { if(type == MaterialAttributeType::String) {
const auto& stringValue = *static_cast<const Containers::StringView*>(value); const auto& stringValue = *static_cast<const Containers::StringView*>(value);

16
src/Magnum/Trade/MaterialData.h

@ -2906,20 +2906,26 @@ template<class T
, class , class
#endif #endif
> constexpr MaterialAttributeData::MaterialAttributeData(const Containers::StringView name, const T& value) noexcept: > constexpr MaterialAttributeData::MaterialAttributeData(const Containers::StringView name, const T& value) noexcept:
_data{Implementation::MaterialAttributeTypeFor<T>::type(), _data{Implementation::MaterialAttributeTypeFor<T>::type(), (
/* It would sort before " LayerName" and that's not desirable */
CORRADE_CONSTEXPR_ASSERT(!name.isEmpty(), "Trade::MaterialAttributeData: name is not allowed to be empty"),
/* MSVC 2015 complains about "error C2065: 'T': undeclared identifier" /* MSVC 2015 complains about "error C2065: 'T': undeclared identifier"
in the lambda inside this macro. Sorry, the assert will be less in the lambda inside this macro. Sorry, the assert will be less
useful on that stupid thing. */ useful on that stupid thing. */
#ifndef CORRADE_MSVC2015_COMPATIBILITY #ifndef CORRADE_MSVC2015_COMPATIBILITY
(CORRADE_CONSTEXPR_ASSERT(name.size() + sizeof(T) + 2 <= Implementation::MaterialAttributeDataSize, "Trade::MaterialAttributeData: name" << name << "too long, expected at most" << Implementation::MaterialAttributeDataSize - sizeof(T) - 2 << "bytes for" << Implementation::MaterialAttributeTypeFor<T>::type() << "but got" << name.size()), name) CORRADE_CONSTEXPR_ASSERT(name.size() + sizeof(T) + 2 <= Implementation::MaterialAttributeDataSize, "Trade::MaterialAttributeData: name" << name << "too long, expected at most" << Implementation::MaterialAttributeDataSize - sizeof(T) - 2 << "bytes for" << Implementation::MaterialAttributeTypeFor<T>::type() << "but got" << name.size()),
#else #else
(CORRADE_CONSTEXPR_ASSERT(name.size() + sizeof(T) + 2 <= Implementation::MaterialAttributeDataSize, "Trade::MaterialAttributeData: name" << name << "too long, got" << name.size() << "bytes"), name) CORRADE_CONSTEXPR_ASSERT(name.size() + sizeof(T) + 2 <= Implementation::MaterialAttributeDataSize, "Trade::MaterialAttributeData: name" << name << "too long, got" << name.size() << "bytes"),
#endif #endif
, value} {} name), value} {}
/* The 4 extra bytes are for a null byte after both the name and value, a type /* The 4 extra bytes are for a null byte after both the name and value, a type
and a string size */ and a string size */
constexpr MaterialAttributeData::MaterialAttributeData(const Containers::StringView name, const Containers::StringView value) noexcept: _data{(CORRADE_CONSTEXPR_ASSERT(name.size() + value.size() + 4 <= Implementation::MaterialAttributeDataSize, "Trade::MaterialAttributeData: name" << name << "and value" << value << "too long, expected at most" << Implementation::MaterialAttributeDataSize - 4 << "bytes in total but got" << name.size() + value.size()), name), value} {} constexpr MaterialAttributeData::MaterialAttributeData(const Containers::StringView name, const Containers::StringView value) noexcept: _data{(
/* It would sort before " LayerName" and that's not desirable */
CORRADE_CONSTEXPR_ASSERT(!name.isEmpty(), "Trade::MaterialAttributeData: name is not allowed to be empty"),
CORRADE_CONSTEXPR_ASSERT(name.size() + value.size() + 4 <= Implementation::MaterialAttributeDataSize, "Trade::MaterialAttributeData: name" << name << "and value" << value << "too long, expected at most" << Implementation::MaterialAttributeDataSize - 4 << "bytes in total but got" << name.size() + value.size()),
name), value} {}
template<class T> T MaterialAttributeData::value() const { template<class T> T MaterialAttributeData::value() const {
CORRADE_ASSERT(Implementation::MaterialAttributeTypeFor<T>::type() == _data.type, CORRADE_ASSERT(Implementation::MaterialAttributeTypeFor<T>::type() == _data.type,

40
src/Magnum/Trade/Test/MaterialDataTest.cpp

@ -73,6 +73,8 @@ class MaterialDataTest: public TestSuite::Tester {
void constructAttributeInvalidLayerName(); void constructAttributeInvalidLayerName();
void constructAttributeWrongTypeForName(); void constructAttributeWrongTypeForName();
void constructAttributeInvalidType(); void constructAttributeInvalidType();
void constructAttributeEmptyName();
void constructAttributeEmptyNameString();
void constructAttributeTooLarge(); void constructAttributeTooLarge();
void constructAttributeTooLargeString(); void constructAttributeTooLargeString();
void constructAttributeTooLargeNameString(); void constructAttributeTooLargeNameString();
@ -214,6 +216,8 @@ MaterialDataTest::MaterialDataTest() {
&MaterialDataTest::constructAttributeInvalidLayerName, &MaterialDataTest::constructAttributeInvalidLayerName,
&MaterialDataTest::constructAttributeWrongTypeForName, &MaterialDataTest::constructAttributeWrongTypeForName,
&MaterialDataTest::constructAttributeInvalidType, &MaterialDataTest::constructAttributeInvalidType,
&MaterialDataTest::constructAttributeEmptyName,
&MaterialDataTest::constructAttributeEmptyNameString,
&MaterialDataTest::constructAttributeTooLarge, &MaterialDataTest::constructAttributeTooLarge,
&MaterialDataTest::constructAttributeTooLargeString, &MaterialDataTest::constructAttributeTooLargeString,
&MaterialDataTest::constructAttributeTooLargeNameString, &MaterialDataTest::constructAttributeTooLargeNameString,
@ -707,6 +711,42 @@ void MaterialDataTest::constructAttributeInvalidType() {
"Trade::materialAttributeTypeSize(): invalid type Trade::MaterialAttributeType(0xfe)\n"); "Trade::materialAttributeTypeSize(): invalid type Trade::MaterialAttributeType(0xfe)\n");
} }
void MaterialDataTest::constructAttributeEmptyName() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
std::ostringstream out;
Error redirectError{&out};
MaterialAttributeData{"", Int{}};
/* Constexpr variant has the same assert, but in the header. It should have
the same output. */
/*constexpr*/ MaterialAttributeData{""_s, Int{}};
CORRADE_COMPARE(out.str(),
"Trade::MaterialAttributeData: name is not allowed to be empty\n"
"Trade::MaterialAttributeData: name is not allowed to be empty\n");
}
void MaterialDataTest::constructAttributeEmptyNameString() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
/* This has no reason to not be allowed */
MaterialAttributeData{"hello this string is empty", ""};
MaterialAttributeData{"hello this string is empty"_s, ""_s};
std::ostringstream out;
Error redirectError{&out};
MaterialAttributeData{"", "hello"};
/* Constexpr variant has the same assert, but in the header. It should have
the same output. */
/*constexpr*/ MaterialAttributeData{""_s, "hello"_s};
CORRADE_COMPARE(out.str(),
"Trade::MaterialAttributeData: name is not allowed to be empty\n"
"Trade::MaterialAttributeData: name is not allowed to be empty\n");
}
void MaterialDataTest::constructAttributeTooLarge() { void MaterialDataTest::constructAttributeTooLarge() {
#ifdef CORRADE_NO_ASSERT #ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");

Loading…
Cancel
Save