encoding: avoid UB when casting to tlv::SignatureTypeValue
Change-Id: I52ec0bef8527b6a52208dc07be75e790e504c47e
Refs: #4370
diff --git a/src/encoding/tlv.cpp b/src/encoding/tlv.cpp
index 4de73a1..712291c 100644
--- a/src/encoding/tlv.cpp
+++ b/src/encoding/tlv.cpp
@@ -1,5 +1,5 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
* Copyright (c) 2013-2017 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
@@ -25,7 +25,7 @@
namespace tlv {
std::ostream&
-operator<<(std::ostream& os, const SignatureTypeValue& signatureType)
+operator<<(std::ostream& os, SignatureTypeValue signatureType)
{
switch (signatureType) {
case SignatureTypeValue::DigestSha256:
diff --git a/src/encoding/tlv.hpp b/src/encoding/tlv.hpp
index 49d61e5..52115f9 100644
--- a/src/encoding/tlv.hpp
+++ b/src/encoding/tlv.hpp
@@ -96,7 +96,7 @@
AppPrivateBlock2 = 32767
};
-enum SignatureTypeValue {
+enum SignatureTypeValue : uint16_t {
DigestSha256 = 0,
SignatureSha256WithRsa = 1,
// <Unassigned> = 2,
@@ -104,7 +104,7 @@
};
std::ostream&
-operator<<(std::ostream& os, const SignatureTypeValue& signatureType);
+operator<<(std::ostream& os, SignatureTypeValue signatureType);
/** @brief TLV-TYPE numbers for SignatureInfo features
* @sa docs/tutorials/certificate-format.rst
diff --git a/src/security/v2/certificate.cpp b/src/security/v2/certificate.cpp
index dc48c3e..31cb81d 100644
--- a/src/security/v2/certificate.cpp
+++ b/src/security/v2/certificate.cpp
@@ -166,7 +166,7 @@
os << "Signature Information:\n";
{
- os << " Signature Type: " << static_cast<tlv::SignatureTypeValue>(cert.getSignature().getType()) << "\n";
+ os << " Signature Type: " << cert.getSignature().getType() << "\n";
if (cert.getSignature().hasKeyLocator()) {
os << " Key Locator: ";
diff --git a/src/signature-info.cpp b/src/signature-info.cpp
index 0b3b0a1..6210eff 100644
--- a/src/signature-info.cpp
+++ b/src/signature-info.cpp
@@ -79,10 +79,11 @@
if (m_hasKeyLocator)
totalLength += m_keyLocator.wireEncode(encoder);
- totalLength += prependNonNegativeIntegerBlock(encoder, tlv::SignatureType, m_type);
-
+ totalLength += prependNonNegativeIntegerBlock(encoder, tlv::SignatureType,
+ static_cast<uint64_t>(m_type));
totalLength += encoder.prependVarNumber(totalLength);
totalLength += encoder.prependVarNumber(tlv::SignatureInfo);
+
return totalLength;
}
@@ -107,6 +108,7 @@
void
SignatureInfo::wireDecode(const Block& wire)
{
+ m_type = -1;
m_hasKeyLocator = false;
m_otherTlvs.clear();
@@ -116,16 +118,15 @@
if (m_wire.type() != tlv::SignatureInfo)
BOOST_THROW_EXCEPTION(Error("Decoding SignatureInfo, but TLV-TYPE is " + to_string(m_wire.type())));
- Block::element_const_iterator it = m_wire.elements_begin();
+ auto it = m_wire.elements_begin();
// the first sub-element must be SignatureType
- if (it != m_wire.elements_end() && it->type() == tlv::SignatureType) {
- m_type = readNonNegativeIntegerAs<int32_t>(*it);
- ++it;
- }
- else
+ if (it == m_wire.elements_end() || it->type() != tlv::SignatureType)
BOOST_THROW_EXCEPTION(Error("Missing SignatureType in SignatureInfo"));
+ m_type = readNonNegativeIntegerAs<tlv::SignatureTypeValue>(*it);
+ ++it;
+
// the second sub-element could be KeyLocator
if (it != m_wire.elements_end() && it->type() == tlv::KeyLocator) {
m_keyLocator.wireDecode(*it);
@@ -228,6 +229,9 @@
std::ostream&
operator<<(std::ostream& os, const SignatureInfo& info)
{
+ if (info.getSignatureType() == -1)
+ return os << "Invalid SignatureInfo";
+
os << static_cast<tlv::SignatureTypeValue>(info.getSignatureType());
if (info.hasKeyLocator()) {
os << " " << info.getKeyLocator();
@@ -239,6 +243,7 @@
}
os << "}";
}
+
return os;
}