From ef6e3af7354584358d757ee0a817cdac5003c9b5 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Fri, 22 Dec 2023 19:44:04 -0600 Subject: [PATCH] [ox/model] Fix infinite recursion caused by have a vector of the same type in ModelValue --- deps/ox/src/ox/mc/read.hpp | 8 ++++---- deps/ox/src/ox/mc/write.hpp | 17 ++++++++++------- deps/ox/src/ox/model/modelhandleradaptor.hpp | 12 ++++++++++-- deps/ox/src/ox/model/modelvalue.hpp | 16 ++++++++-------- deps/ox/src/ox/oc/read.hpp | 2 +- 5 files changed, 33 insertions(+), 22 deletions(-) diff --git a/deps/ox/src/ox/mc/read.hpp b/deps/ox/src/ox/mc/read.hpp index 2338b6f2..911807d0 100644 --- a/deps/ox/src/ox/mc/read.hpp +++ b/deps/ox/src/ox/mc/read.hpp @@ -265,10 +265,10 @@ constexpr Error MetalClawReaderTemplate::field(const char *name, T *val) // set size of val if the field is present, don't worry about it if not if (m_fieldPresence.get(static_cast(m_field))) { oxRequire(len, arrayLength(name, false)); - val->resize(len); + oxReturnError(ox::resizeVector(*val, len)); return field(name, val->data(), val->size()); } - val->resize(0); + oxReturnError(ox::resizeVector(*val, 0)); } ++m_field; return {}; @@ -302,12 +302,12 @@ template constexpr Error MetalClawReaderTemplate::field(const char*, UnionView val) noexcept { if ((!m_unionIdx.has_value() || static_cast(*m_unionIdx) == m_field) && val.get()) { if (m_fieldPresence.get(static_cast(m_field))) { - auto reader = child("", ox::Optional(ox::in_place_t{}, val.idx())); + auto reader = child("", ox::Optional(ox::in_place, val.idx())); oxReturnError(model(reader.interface(), val.get())); } } ++m_field; - return OxError(0); + return {}; } template diff --git a/deps/ox/src/ox/mc/write.hpp b/deps/ox/src/ox/mc/write.hpp index 9b3c1015..97968599 100644 --- a/deps/ox/src/ox/mc/write.hpp +++ b/deps/ox/src/ox/mc/write.hpp @@ -261,15 +261,16 @@ constexpr Error MetalClawWriter::field(const char*, const T *val) noexce } else { bool fieldSet = false; if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { + auto const writeIdx = m_writer.tellp(); MetalClawWriter writer(m_writer); ModelHandlerInterface> handler{&writer}; oxReturnError(model(&handler, val)); oxReturnError(writer.finalize()); - fieldSet = true; + fieldSet = writeIdx != m_writer.tellp(); } oxReturnError(m_fieldPresence.set(static_cast(m_field), fieldSet)); ++m_field; - return OxError(0); + return {}; } } @@ -278,15 +279,16 @@ template constexpr Error MetalClawWriter::field(const char*, UnionView val) noexcept { bool fieldSet = false; if (val.get() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) { + auto const writeIdx = m_writer.tellp(); MetalClawWriter writer(m_writer, ox::Optional(ox::in_place, val.idx())); ModelHandlerInterface handler{&writer}; oxReturnError(model(&handler, val.get())); oxReturnError(writer.finalize()); - fieldSet = true; + fieldSet = writeIdx != m_writer.tellp(); } oxReturnError(m_fieldPresence.set(static_cast(m_field), fieldSet)); ++m_field; - return OxError(0); + return {}; } template @@ -297,15 +299,16 @@ constexpr Error MetalClawWriter::field(const char*, const T *val, std::s // write the length const auto arrLen = mc::encodeInteger(len); oxReturnError(m_writer.write(reinterpret_cast(arrLen.data), arrLen.length)); + auto const writeIdx = m_writer.tellp(); MetalClawWriter writer(m_writer); ModelHandlerInterface handler{&writer}; oxReturnError(handler.template setTypeInfo("List", 0, {}, static_cast(len))); // write the array - for (std::size_t i = 0; i < len; i++) { + for (std::size_t i = 0; i < len; ++i) { oxReturnError(handler.field("", &val[i])); } oxReturnError(writer.finalize()); - fieldSet = true; + fieldSet = writeIdx != m_writer.tellp(); } oxReturnError(m_fieldPresence.set(static_cast(m_field), fieldSet)); ++m_field; @@ -337,7 +340,7 @@ constexpr Error MetalClawWriter::field(const char*, const HashMap @@ -215,7 +214,16 @@ class ModelHandlerBase { static constexpr ox::OpType opType() noexcept { return opType_v; } - }; + +constexpr ox::Error resizeVector(auto &vec, size_t sz) { + if constexpr(ox::is_same_v) { + return vec.resize(sz); + } else { + vec.resize(sz); + return {}; + } +} + } diff --git a/deps/ox/src/ox/model/modelvalue.hpp b/deps/ox/src/ox/model/modelvalue.hpp index 2bacf6b1..fd63c3a3 100644 --- a/deps/ox/src/ox/model/modelvalue.hpp +++ b/deps/ox/src/ox/model/modelvalue.hpp @@ -202,7 +202,8 @@ class ModelValue { class ModelValueVector { private: Vector m_vec; - ModelValue m_templateValue; + const DescriptorType *m_type = nullptr; + int m_typeSubscriptLevels = 0; String m_typeName; int m_typeVersion = 0; @@ -227,14 +228,15 @@ class ModelValueVector { return m_vec.data(); } - constexpr void resize(std::size_t sz) noexcept { + constexpr ox::Error resize(std::size_t sz) noexcept { const auto oldSz = m_vec.size(); m_vec.resize(sz); if (sz > oldSz) { for (auto i = oldSz; i < sz; ++i) { - m_vec[i] = m_templateValue; + oxReturnError(m_vec[i].setType(m_type, m_typeSubscriptLevels)); } } + return {}; } [[nodiscard]] @@ -248,7 +250,9 @@ class ModelValueVector { } constexpr Error setType(const DescriptorType *type, int subscriptLevels) noexcept { - return m_templateValue.setType(type, subscriptLevels); + m_type = type; + m_typeSubscriptLevels = subscriptLevels; + return {}; } [[nodiscard]] @@ -1089,14 +1093,12 @@ constexpr ModelValueVector::ModelValueVector(const ModelValueVector &other) noex for (auto &v : other.m_vec) { m_vec.emplace_back(v); } - m_templateValue = other.m_templateValue; m_typeName = other.m_typeName; m_typeVersion = other.m_typeVersion; } constexpr ModelValueVector::ModelValueVector(ModelValueVector &&other) noexcept { m_vec = std::move(other.m_vec); - m_templateValue = std::move(other.m_templateValue); m_typeName = std::move(other.m_typeName); m_typeVersion = other.m_typeVersion; } @@ -1108,7 +1110,6 @@ constexpr ModelValueVector &ModelValueVector::operator=(const ModelValueVector & for (auto &v : other.m_vec) { m_vec.emplace_back(v); } - m_templateValue = other.m_templateValue; m_typeName = other.m_typeName; m_typeVersion = other.m_typeVersion; return *this; @@ -1119,7 +1120,6 @@ constexpr ModelValueVector &ModelValueVector::operator=(ModelValueVector &&other return *this; } m_vec = std::move(other.m_vec); - m_templateValue = std::move(other.m_templateValue); m_typeName = std::move(other.m_typeName); m_typeVersion = other.m_typeVersion; return *this; diff --git a/deps/ox/src/ox/oc/read.hpp b/deps/ox/src/ox/oc/read.hpp index 2b55a436..812da108 100644 --- a/deps/ox/src/ox/oc/read.hpp +++ b/deps/ox/src/ox/oc/read.hpp @@ -147,7 +147,7 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept { if constexpr(isVector_v) { const auto &srcVal = value(key); const auto srcSize = srcVal.size(); - val->resize(srcSize); + oxReturnError(ox::resizeVector(*val, srcSize)); err = field(key, val->data(), val->size()); } else if constexpr(isArray_v) { const auto &srcVal = value(key);