meta-info: prevent FreshnessPeriod overflow
refs #4997
Change-Id: I22ae27257fd79b539a8ac137f8b1871e1b988cf8
diff --git a/ndn-cxx/meta-info.cpp b/ndn-cxx/meta-info.cpp
index ce04687..3e4d6f1 100644
--- a/ndn-cxx/meta-info.cpp
+++ b/ndn-cxx/meta-info.cpp
@@ -42,14 +42,23 @@
return *this;
}
+time::milliseconds
+MetaInfo::getFreshnessPeriod() const
+{
+ if (m_freshnessPeriod > static_cast<uint64_t>(time::milliseconds::max().count())) {
+ return time::milliseconds::max();
+ }
+ return time::milliseconds(m_freshnessPeriod);
+}
+
MetaInfo&
MetaInfo::setFreshnessPeriod(time::milliseconds freshnessPeriod)
{
- if (freshnessPeriod < time::milliseconds::zero()) {
+ if (freshnessPeriod < 0_ms) {
NDN_THROW(std::invalid_argument("FreshnessPeriod must be >= 0"));
}
m_wire.reset();
- m_freshnessPeriod = freshnessPeriod;
+ m_freshnessPeriod = static_cast<uint64_t>(freshnessPeriod.count());
return *this;
}
@@ -135,9 +144,8 @@
}
// FreshnessPeriod
- if (m_freshnessPeriod != DEFAULT_FRESHNESS_PERIOD) {
- totalLength += prependNonNegativeIntegerBlock(encoder, tlv::FreshnessPeriod,
- static_cast<uint64_t>(m_freshnessPeriod.count()));
+ if (m_freshnessPeriod != static_cast<uint64_t>(DEFAULT_FRESHNESS_PERIOD.count())) {
+ totalLength += prependNonNegativeIntegerBlock(encoder, tlv::FreshnessPeriod, m_freshnessPeriod);
}
// ContentType
@@ -193,11 +201,11 @@
// FreshnessPeriod
if (val != m_wire.elements_end() && val->type() == tlv::FreshnessPeriod) {
- m_freshnessPeriod = time::milliseconds(readNonNegativeInteger(*val));
+ m_freshnessPeriod = readNonNegativeInteger(*val);
++val;
}
else {
- m_freshnessPeriod = DEFAULT_FRESHNESS_PERIOD;
+ m_freshnessPeriod = static_cast<uint64_t>(DEFAULT_FRESHNESS_PERIOD.count());
}
// FinalBlockId
diff --git a/ndn-cxx/meta-info.hpp b/ndn-cxx/meta-info.hpp
index 886e8a3..5f0df92 100644
--- a/ndn-cxx/meta-info.hpp
+++ b/ndn-cxx/meta-info.hpp
@@ -102,15 +102,15 @@
MetaInfo&
setType(uint32_t type);
- /** @brief Return the value of `FreshnessPeriod`.
+ /**
+ * @brief Return the value of `FreshnessPeriod`.
*
- * If the `FreshnessPeriod` element is not present, returns #DEFAULT_FRESHNESS_PERIOD.
+ * If the `FreshnessPeriod` element is not present, returns #DEFAULT_FRESHNESS_PERIOD.
+ * If the `FreshnessPeriod` value is not representable in the return type, it's clamped to
+ * the nearest representable value.
*/
time::milliseconds
- getFreshnessPeriod() const
- {
- return m_freshnessPeriod;
- }
+ getFreshnessPeriod() const;
/** @brief Set `FreshnessPeriod`.
* @throw std::invalid_argument specified FreshnessPeriod is negative
@@ -196,7 +196,7 @@
private:
uint32_t m_type = tlv::ContentType_Blob;
- time::milliseconds m_freshnessPeriod = DEFAULT_FRESHNESS_PERIOD;
+ uint64_t m_freshnessPeriod = static_cast<uint64_t>(DEFAULT_FRESHNESS_PERIOD.count());
std::optional<name::Component> m_finalBlockId;
std::list<Block> m_appMetaInfo;
diff --git a/tests/unit/meta-info.t.cpp b/tests/unit/meta-info.t.cpp
index 2e37ea5..bd5aee4 100644
--- a/tests/unit/meta-info.t.cpp
+++ b/tests/unit/meta-info.t.cpp
@@ -78,6 +78,19 @@
BOOST_CHECK_EQUAL(b.wireEncode(), wire3);
}
+BOOST_AUTO_TEST_CASE(FreshnessPeriodOverflow)
+{
+ // Bug #4997
+ MetaInfo mi0("140A 19087FFFFFFFFFFFFFFF"_block);
+ BOOST_CHECK_EQUAL(mi0.getFreshnessPeriod(), 0x7FFFFFFFFFFFFFFF_ms);
+
+ MetaInfo mi1("140A 19088000000000000000"_block);
+ BOOST_CHECK_EQUAL(mi1.getFreshnessPeriod(), time::milliseconds::max());
+
+ MetaInfo mi2("140A 1908FFFFFFFFFFFFFFFF"_block);
+ BOOST_CHECK_EQUAL(mi2.getFreshnessPeriod(), time::milliseconds::max());
+}
+
BOOST_AUTO_TEST_CASE(AppMetaInfo)
{
MetaInfo info1;