diff --git a/groups/nts/ntsa/ntsa_ipv4address.cpp b/groups/nts/ntsa/ntsa_ipv4address.cpp index 87c5172c..119d1906 100644 --- a/groups/nts/ntsa/ntsa_ipv4address.cpp +++ b/groups/nts/ntsa/ntsa_ipv4address.cpp @@ -19,10 +19,13 @@ BSLS_IDENT_RCSID(ntsa_ipv4address_cpp, "$Id$ $CSID$") #include +#include #include #include +#include #include + namespace BloombergLP { namespace ntsa { @@ -90,22 +93,25 @@ bool Ipv4Address::parse(const bslstl::StringRef& text) NTSCFG_NOEXCEPT Representation newValue; newValue.d_asDword = 0; - bsl::uint32_t byteAtIndex = 0; + bsl::uint64_t numAtIndex = 0; while (current != end) { const char ch = *current; if (NTSCFG_LIKELY(ch >= '0' && ch <= '9')) { - byteAtIndex *= 10; - byteAtIndex += ch - '0'; + numAtIndex *= 10; + numAtIndex += ch - '0'; + if (numAtIndex > bsl::numeric_limits::max()) { + return false; + } } else { if (ch == '.') { - if (byteAtIndex > 255) { + if (numAtIndex > 255) { return false; } newValue.d_asBytes[index] = - NTSCFG_WARNING_NARROW(bsl::uint8_t, byteAtIndex); - byteAtIndex = 0; + NTSCFG_WARNING_NARROW(bsl::uint8_t, numAtIndex); + numAtIndex = 0; ++index; if (index > 3) { return false; @@ -119,17 +125,18 @@ bool Ipv4Address::parse(const bslstl::StringRef& text) NTSCFG_NOEXCEPT ++current; } - if (index != 3) { + bsl::uint64_t numOctetsLeft = 4 - index; + if (numAtIndex >= bsl::pow(256,numOctetsLeft)) { return false; } - if (byteAtIndex > 255) { - return false; + for (size_t oct = 0; oct < numOctetsLeft; ++oct) { + bsl::uint8_t octet = NTSCFG_WARNING_NARROW(bsl::uint8_t, + numAtIndex % 256); + newValue.d_asBytes[3 - oct] = octet; + numAtIndex /= 256; } - newValue.d_asBytes[index] = - NTSCFG_WARNING_NARROW(bsl::uint8_t, byteAtIndex); - d_value.d_asDword = newValue.d_asDword; return true; diff --git a/groups/nts/ntsa/ntsa_ipv4address.t.cpp b/groups/nts/ntsa/ntsa_ipv4address.t.cpp index e028ceb1..32f494b3 100644 --- a/groups/nts/ntsa/ntsa_ipv4address.t.cpp +++ b/groups/nts/ntsa/ntsa_ipv4address.t.cpp @@ -291,6 +291,20 @@ void Ipv4AddressTest::verifyParsing() { "x.2.3.4.5", {0x00, 0x00, 0x00, 0x00}, false}, { "256.256.256.256", {0x00, 0x00, 0x00, 0x00}, false}, {"9999.9999.9999.9999", {0x00, 0x00, 0x00, 0x00}, false}, + + { "127.1", {0x7F, 0x00, 0x00, 0x01}, true}, + { "127.168.257", {0x7F, 0xA8, 0x01, 0x01}, true}, + { "127.2.1", {0x7F, 0x02, 0x00, 0x01}, true}, + { "199.11315476", {0xC7, 0xAC, 0xA9, 0x14}, true}, + { "255.16777215", {0xFF, 0xFF, 0xFF, 0xFF}, true}, + { "255.255.65535", {0xFF, 0xFF, 0xFF, 0xFF}, true}, + { "1", {0x00, 0x00, 0x00, 0x01}, true}, + { "4294967295", {0xFF, 0xFF, 0xFF, 0xFF}, true}, + { "4294967296", {0x00, 0x00, 0x00, 0x00}, false}, + { "256.1", {0x00, 0x00, 0x00, 0x00}, false}, + { "255.16777216", {0x00, 0x00, 0x00, 0x00}, false}, + { "255.255.65536", {0xFF, 0xFF, 0xFF, 0xFF}, false}, + { "99999999999999999", {0x00, 0x00, 0x00, 0x00}, false}, }; enum { NUM_DATA = sizeof(DATA) / sizeof(DATA[0]) };