From: tho Date: Thu, 10 Nov 2011 13:33:27 +0000 (+0000) Subject: Termlib: fixed endian bug while reading terminfo file X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=b2fff1b50e0010fdad28cb638987cbf88032e30e;p=senf.git Termlib: fixed endian bug while reading terminfo file 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 --- diff --git a/senf/Socket/Protocols/INet/INet4Address.cc b/senf/Socket/Protocols/INet/INet4Address.cc index 618bdb2..d37f54f 100644 --- a/senf/Socket/Protocols/INet/INet4Address.cc +++ b/senf/Socket/Protocols/INet/INet4Address.cc @@ -39,7 +39,6 @@ #if defined(_REENTRANT) && !defined(__GLIBC__) #include #endif -#include //#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(std::string(s,i+1)); + prefix_len_ = prefix_len_checked(boost::lexical_cast(std::string(s,i+1))); } catch (boost::bad_lexical_cast const &) { throw AddressSyntaxException(s); } diff --git a/senf/Socket/Protocols/INet/INet4Address.cci b/senf/Socket/Protocols/INet/INet4Address.cci index 40024ca..0232dd9 100644 --- a/senf/Socket/Protocols/INet/INet4Address.cci +++ b/senf/Socket/Protocols/INet/INet4Address.cci @@ -29,6 +29,7 @@ \brief INet4Address inline non-template implementation */ // Custom includes +#include #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(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) diff --git a/senf/Socket/Protocols/INet/INet4Address.hh b/senf/Socket/Protocols/INet/INet4Address.hh index be54958..93908b3 100644 --- a/senf/Socket/Protocols/INet/INet4Address.hh +++ b/senf/Socket/Protocols/INet/INet4Address.hh @@ -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_; diff --git a/senf/Socket/Protocols/INet/INet4Address.test.cc b/senf/Socket/Protocols/INet/INet4Address.test.cc index ee65131..aa05818 100644 --- a/senf/Socket/Protocols/INet/INet4Address.test.cc +++ b/senf/Socket/Protocols/INet/INet4Address.test.cc @@ -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")); } } diff --git a/senf/Socket/Protocols/INet/INet6Address.cc b/senf/Socket/Protocols/INet/INet6Address.cc index da06e11..487a952 100644 --- a/senf/Socket/Protocols/INet/INet6Address.cc +++ b/senf/Socket/Protocols/INet/INet6Address.cc @@ -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(std::string(s,i+1)); + prefix_len_ = prefix_len_checked( boost::lexical_cast(std::string(s,i+1))); } catch (boost::bad_lexical_cast const &) { throw AddressSyntaxException(s); } diff --git a/senf/Socket/Protocols/INet/INet6Address.cci b/senf/Socket/Protocols/INet/INet6Address.cci index 4e3d7f7..3c2ac14 100644 --- a/senf/Socket/Protocols/INet/INet6Address.cci +++ b/senf/Socket/Protocols/INet/INet6Address.cci @@ -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(prefix_len)); + return prefix_len; +} + prefix_ std::ostream & senf::operator<<(std::ostream & os, INet6Network const & addr) { os << addr.address() << '/' << addr.prefix_len(); diff --git a/senf/Socket/Protocols/INet/INet6Address.hh b/senf/Socket/Protocols/INet/INet6Address.hh index cf43b8d..505ca3d 100644 --- a/senf/Socket/Protocols/INet/INet6Address.hh +++ b/senf/Socket/Protocols/INet/INet6Address.hh @@ -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 diff --git a/senf/Socket/Protocols/INet/INet6Address.test.cc b/senf/Socket/Protocols/INet/INet6Address.test.cc index ec03f8d..1528f20 100644 --- a/senf/Socket/Protocols/INet/INet6Address.test.cc +++ b/senf/Socket/Protocols/INet/INet6Address.test.cc @@ -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; diff --git a/senf/Utils/Termlib/Terminfo.cc b/senf/Utils/Termlib/Terminfo.cc index b1eb5c8..a3ae123 100644 --- a/senf/Utils/Termlib/Terminfo.cc +++ b/senf/Utils/Termlib/Terminfo.cc @@ -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(static_cast(&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(static_cast(&v)), sizeof(v)); if (!is) throw InvalidTerminfoException(); - *i = v; + *i = le16toh(v); } stringPool_.resize(h.stringPoolSz); diff --git a/senf/Utils/Termlib/Terminfo.hh b/senf/Utils/Termlib/Terminfo.hh index 52137fa..42e61a7 100644 --- a/senf/Utils/Termlib/Terminfo.hh +++ b/senf/Utils/Termlib/Terminfo.hh @@ -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 BoolVec; @@ -227,7 +228,7 @@ namespace term { typedef std::vector StringVec; typedef std::vector StringPool; - std::string findTerminfo(std::string const & name); + static std::string findTerminfo(std::string const & name); void load(std::istream & is); std::string name_;