Termlib: fixed endian bug while reading terminfo file
tho [Thu, 10 Nov 2011 13:33:27 +0000 (13:33 +0000)]
INet[46]Network: check if prefix_length is in valid range

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1825 270642c3-0616-0410-b53a-bc976706d245

senf/Socket/Protocols/INet/INet4Address.cc
senf/Socket/Protocols/INet/INet4Address.cci
senf/Socket/Protocols/INet/INet4Address.hh
senf/Socket/Protocols/INet/INet4Address.test.cc
senf/Socket/Protocols/INet/INet6Address.cc
senf/Socket/Protocols/INet/INet6Address.cci
senf/Socket/Protocols/INet/INet6Address.hh
senf/Socket/Protocols/INet/INet6Address.test.cc
senf/Utils/Termlib/Terminfo.cc
senf/Utils/Termlib/Terminfo.hh

index 618bdb2..d37f54f 100644 (file)
@@ -39,7 +39,6 @@
 #if defined(_REENTRANT) && !defined(__GLIBC__)
 #include <boost/thread/mutex.hpp>
 #endif
-#include <senf/Socket/Protocols/AddressExceptions.hh>
 
 //#include "INet4Address.mpp"
 #define prefix_
@@ -137,7 +136,7 @@ prefix_ senf::INet4Network::INet4Network(std::string const & s)
     if (i == std::string::npos)
         throw AddressSyntaxException(s);
     try {
-        prefix_len_ = boost::lexical_cast<unsigned>(std::string(s,i+1));
+        prefix_len_ = prefix_len_checked(boost::lexical_cast<unsigned>(std::string(s,i+1)));
     } catch (boost::bad_lexical_cast const &) {
         throw AddressSyntaxException(s);
     }
index 40024ca..0232dd9 100644 (file)
@@ -29,6 +29,7 @@
     \brief INet4Address inline non-template implementation */
 
 // Custom includes
+#include <senf/Socket/Protocols/AddressExceptions.hh>
 
 #define prefix_ inline
 //-/////////////////////////////////////////////////////////////////////////////////////////////////
@@ -86,22 +87,6 @@ prefix_ bool senf::INet4Address::boolean_test()
 //-/////////////////////////////////////////////////////////////////////////////////////////////////
 // senf::INet4Network
 
-prefix_ unsigned senf::INet4Network::prefix_len()
-    const
-{
-    return prefix_len_;
-}
-
-//-/////////////////////////////////////////////////////////////////////////////////////////////////
-// private members
-
-prefix_ boost::uint32_t senf::INet4Network::mask()
-    const
-{
-    // This is correct as long as the system is using 2-complement arithmetic ...
-    return (~((boost::uint32_t(1u)<<(32u-prefix_len()))-1u)) & 0xFFFFFFFFu;
-}
-
 //-/////////////////////////////////////////////////////////////////////////////////////////////////
 // public members
 
@@ -110,7 +95,8 @@ prefix_ senf::INet4Network::INet4Network()
 {}
 
 prefix_ senf::INet4Network::INet4Network(INet4Address const & address, unsigned prefix_len)
-    : prefix_len_(prefix_len), address_(INet4Address(address.address() & mask()))
+    : prefix_len_( prefix_len_checked(prefix_len)),
+      address_(INet4Address(address.address() & mask()))
 {}
 
 prefix_ senf::INet4Address const & senf::INet4Network::address()
@@ -119,6 +105,12 @@ prefix_ senf::INet4Address const & senf::INet4Network::address()
     return address_;
 }
 
+prefix_ unsigned senf::INet4Network::prefix_len()
+    const
+{
+    return prefix_len_;
+}
+
 prefix_ bool senf::INet4Network::boolean_test()
     const
 {
@@ -154,6 +146,25 @@ prefix_ senf::INet4Network senf::INet4Network::subnet(boost::uint32_t net, unsig
 }
 
 //-/////////////////////////////////////////////////////////////////////////////////////////////////
+// private members
+
+prefix_ unsigned senf::INet4Network::prefix_len_checked(unsigned prefix_len)
+    const
+{
+    if (prefix_len > 32)
+        throw AddressSyntaxException("invalid INet4 prefix length: " +
+                boost::lexical_cast<std::string>(prefix_len));
+    return prefix_len;
+}
+
+prefix_ boost::uint32_t senf::INet4Network::mask()
+    const
+{
+    // This is correct as long as the system is using 2-complement arithmetic ...
+    return (~((boost::uint32_t(1u)<<(32u-prefix_len()))-1u)) & 0xFFFFFFFFu;
+}
+
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
 // namespace members
 
 prefix_ std::ostream & senf::operator<<(std::ostream & os, INet4Network const & addr)
index be54958..93908b3 100644 (file)
@@ -273,6 +273,7 @@ namespace senf {
 
     private:
         boost::uint32_t mask() const;
+        unsigned prefix_len_checked(unsigned prefix_len) const;
 
         unsigned prefix_len_;
         INet4Address address_;
index ee65131..aa05818 100644 (file)
@@ -123,6 +123,7 @@ SENF_AUTO_UNIT_TEST(inet4Network)
 
     BOOST_CHECK_THROW( senf::INet4Network(""), senf::AddressSyntaxException );
     BOOST_CHECK_THROW( senf::INet4Network("192.0.2.0/24/beef"), senf::AddressSyntaxException );
+    BOOST_CHECK_THROW( senf::INet4Network("128.129.130.131/128"), senf::AddressSyntaxException );
 
     {
         std::stringstream str;
@@ -132,12 +133,12 @@ SENF_AUTO_UNIT_TEST(inet4Network)
     }
     {
         std::stringstream str;
-        senf::INet4Network net ("128.129.130.131/128");
+        senf::INet4Network net ("128.129.130.131/32");
         str << net;
-        BOOST_CHECK_EQUAL( str.str(), "128.129.130.131/128");
+        BOOST_CHECK_EQUAL( str.str(), "128.129.130.131/32");
         str >> net;
         BOOST_CHECK( ! str.fail());
-        BOOST_CHECK_EQUAL(net, senf::INet4Network("128.129.130.131/128"));
+        BOOST_CHECK_EQUAL(net, senf::INet4Network("128.129.130.131/32"));
     }
 }
 
index da06e11..487a952 100644 (file)
@@ -172,7 +172,7 @@ prefix_ senf::INet6Network::INet6Network(std::string const & s)
     if (i == std::string::npos)
         throw AddressSyntaxException(s);
     try {
-        prefix_len_ = boost::lexical_cast<unsigned>(std::string(s,i+1));
+        prefix_len_ = prefix_len_checked( boost::lexical_cast<unsigned>(std::string(s,i+1)));
     } catch (boost::bad_lexical_cast const &) {
         throw AddressSyntaxException(s);
     }
index 4e3d7f7..3c2ac14 100644 (file)
@@ -214,7 +214,8 @@ prefix_ senf::INet6Network::INet6Network()
 {}
 
 prefix_ senf::INet6Network::INet6Network(INet6Address const & address, unsigned prefix_len)
-    : prefix_len_(prefix_len), address_(address)
+    : prefix_len_( prefix_len_checked(prefix_len)),
+      address_(address)
 {
     using boost::lambda::_1;
     using boost::lambda::_2;
@@ -282,6 +283,15 @@ prefix_ senf::INet6Network senf::INet6Network::subnet(boost::uint64_t net, unsig
     return INet6Network(addr, prefix_len);
 }
 
+prefix_ unsigned senf::INet6Network::prefix_len_checked(unsigned prefix_len)
+    const
+{
+    if (prefix_len > 128)
+        throw AddressSyntaxException("invalid INet6 prefix length: " +
+                boost::lexical_cast<std::string>(prefix_len));
+    return prefix_len;
+}
+
 prefix_ std::ostream & senf::operator<<(std::ostream & os, INet6Network const & addr)
 {
     os << addr.address() << '/' << addr.prefix_len();
index cf43b8d..505ca3d 100644 (file)
@@ -397,6 +397,8 @@ namespace senf {
     private:
         unsigned prefix_len_;
         INet6Address address_;
+
+        unsigned prefix_len_checked(unsigned prefix_len) const;
     };
 
     /** \brief Output INet6Network instance as it's string representation
index ec03f8d..1528f20 100644 (file)
@@ -210,6 +210,7 @@ SENF_AUTO_UNIT_TEST(inet6Network)
 
     BOOST_CHECK_THROW( INet6Network(""), AddressSyntaxException );
     BOOST_CHECK_THROW( INet6Network("2001:db8:1234::/beef"), AddressSyntaxException );
+    BOOST_CHECK_THROW( INet6Network("2001:db8:1234::/129"), AddressSyntaxException );
 
     {
         std::stringstream str;
index b1eb5c8..a3ae123 100644 (file)
@@ -134,6 +134,13 @@ char const * const senf::term::Terminfo::properties::StringNames[] = {
 //-/////////////////////////////////////////////////////////////////////////////////////////////////
 // senf::term::Terminfo
 
+prefix_ senf::term::Terminfo::InvalidTerminfoException::InvalidTerminfoException(std::string const & term)
+    : senf::Exception("Unreadable terminfo file")
+{
+    if (!term.empty())
+        append( ": " + term);
+}
+
 prefix_ senf::term::Terminfo::Terminfo()
 {}
 
@@ -145,10 +152,15 @@ prefix_ senf::term::Terminfo::Terminfo(std::string const & term)
 prefix_ void senf::term::Terminfo::load(std::string const & term)
 {
     std::string filename (findTerminfo(term));
-    if (filename.empty()) throw InvalidTerminfoException();
+    if (filename.empty()) throw InvalidTerminfoException(term);
     std::ifstream is (filename.c_str());
-    if (!is) throw InvalidTerminfoException();
-    load(is);
+    if (!is) throw InvalidTerminfoException(filename);
+    try {
+        load(is);
+    } catch (InvalidTerminfoException & ex) {
+        ex << ": " << filename;
+        throw ex;
+    }
 }
 
 prefix_ bool senf::term::Terminfo::getFlag(properties::Boolean p)
@@ -399,6 +411,15 @@ namespace {
         boost::uint16_t nNumbers;
         boost::uint16_t nStrings;
         boost::uint16_t stringPoolSz;
+
+        void letoh() {
+            magic = le16toh(magic);
+            namesSz = le16toh(namesSz);
+            nBooleans = le16toh(nBooleans);
+            nNumbers = le16toh(nNumbers);
+            nStrings = le16toh(nStrings);
+            stringPoolSz = le16toh(stringPoolSz);
+        }
     };
 
 }
@@ -407,7 +428,9 @@ prefix_ void senf::term::Terminfo::load(std::istream & is)
 {
     TerminfoHeader h;
     is.read(static_cast<char*>(static_cast<void*>(&h)), sizeof(h));
-    if (!is || h.magic != TerminfoMagic) throw InvalidTerminfoException();
+    h.letoh();
+    if (!is || h.magic != TerminfoMagic) throw InvalidTerminfoException(
+            "invalid magic number (") << h.magic << "!=" << TerminfoMagic << ")";
 
     name_.resize(h.namesSz);
     is.read(&(name_[0]), name_.size());
@@ -445,7 +468,7 @@ prefix_ void senf::term::Terminfo::load(std::istream & is)
         number_t v;
         is.read(static_cast<char*>(static_cast<void*>(&v)), sizeof(v));
         if (!is) throw InvalidTerminfoException();
-        *i = v;
+        *i = le16toh(v);
     }
 
     stringPool_.resize(h.stringPoolSz);
index 52137fa..42e61a7 100644 (file)
@@ -218,8 +218,9 @@ namespace term {
         void dump(std::ostream & os) const; ///< Dump a description of the terminfo entry
 
         /** \brief Invalid, incomplete or non-existent terminfo entry exception */
-        struct InvalidTerminfoException : public senf::Exception
-        { InvalidTerminfoException() : senf::Exception("Unreadable terminfo file") {} };
+        struct InvalidTerminfoException : public senf::Exception {
+            InvalidTerminfoException(std::string const & term = "");
+        };
 
     private:
         typedef std::vector<bool> BoolVec;
@@ -227,7 +228,7 @@ namespace term {
         typedef std::vector<string_t> StringVec;
         typedef std::vector<char> StringPool;
 
-        std::string findTerminfo(std::string const & name);
+        static std::string findTerminfo(std::string const & name);
         void load(std::istream & is);
 
         std::string name_;