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;
 }
 
diff --git a/tests/unit-tests/encoding/tlv.t.cpp b/tests/unit-tests/encoding/tlv.t.cpp
index 52b46ad..6a14c68 100644
--- a/tests/unit-tests/encoding/tlv.t.cpp
+++ b/tests/unit-tests/encoding/tlv.t.cpp
@@ -469,17 +469,10 @@
 
 BOOST_AUTO_TEST_CASE(PrintSignatureTypeValue)
 {
-  SignatureTypeValue value = DigestSha256;
-  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(value), "DigestSha256");
-
-  value = SignatureSha256WithRsa;
-  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(value), "SignatureSha256WithRsa");
-
-  value = SignatureSha256WithEcdsa;
-  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(value), "SignatureSha256WithEcdsa");
-
-  value = static_cast<SignatureTypeValue>(-1);
-  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(value), "Unknown Signature Type");
+  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(DigestSha256), "DigestSha256");
+  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(SignatureSha256WithRsa), "SignatureSha256WithRsa");
+  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(SignatureSha256WithEcdsa), "SignatureSha256WithEcdsa");
+  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(static_cast<SignatureTypeValue>(200)), "Unknown Signature Type");
 }
 
 BOOST_AUTO_TEST_SUITE_END() // PrintHelpers
diff --git a/tests/unit-tests/security/signing-info.t.cpp b/tests/unit-tests/security/signing-info.t.cpp
index 2b40a09..9a64a53 100644
--- a/tests/unit-tests/security/signing-info.t.cpp
+++ b/tests/unit-tests/security/signing-info.t.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).
@@ -191,12 +191,12 @@
   info2 = SigningInfo("id:/my-id");
   info1.setDigestAlgorithm(DigestAlgorithm::SHA256);
   info2.setDigestAlgorithm(DigestAlgorithm::SHA256);
-  SignatureInfo sigInfo1(tlv::SignatureTypeValue::DigestSha256);
+  SignatureInfo sigInfo1(tlv::DigestSha256);
   info1.setSignatureInfo(sigInfo1);
   info2.setSignatureInfo(sigInfo1);
   BOOST_CHECK_EQUAL(info1, info2);
   // Change signature info, check inequality
-  SignatureInfo sigInfo2(tlv::SignatureTypeValue::SignatureSha256WithRsa);
+  SignatureInfo sigInfo2(tlv::SignatureSha256WithRsa);
   info2.setSignatureInfo(sigInfo2);
   BOOST_CHECK_NE(info1, info2);
 }
diff --git a/tests/unit-tests/signature-info.t.cpp b/tests/unit-tests/signature-info.t.cpp
index 828bcf8..9ca9cff 100644
--- a/tests/unit-tests/signature-info.t.cpp
+++ b/tests/unit-tests/signature-info.t.cpp
@@ -50,6 +50,8 @@
   BOOST_CHECK_EQUAL(info.hasKeyLocator(), false);
   BOOST_CHECK_THROW(info.getKeyLocator(), SignatureInfo::Error);
 
+  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(info), "Invalid SignatureInfo");
+
   SignatureInfo sha256Info(tlv::DigestSha256);
   BOOST_CHECK_EQUAL(sha256Info.getSignatureType(), tlv::DigestSha256);
   BOOST_CHECK_EQUAL(sha256Info.hasKeyLocator(), false);