From 6644b370a69c30113b7136b57c52bbd92d7af859 Mon Sep 17 00:00:00 2001 From: Yedidya Feldblum Date: Tue, 29 Mar 2016 12:53:16 -0700 Subject: [PATCH] IPAddressV[46]::validate Summary:[Folly] `IPAddressV[46]::validate(StringPiece)`. Just perform the check without allocations or throws. Reviewed By: meyering Differential Revision: D3103545 fb-gh-sync-id: 2918c1398935738f597b9045cf7dadbe42da2527 fbshipit-source-id: 2918c1398935738f597b9045cf7dadbe42da2527 --- folly/IPAddressV4.cpp | 9 +++++++++ folly/IPAddressV4.h | 2 ++ folly/IPAddressV6.cpp | 14 ++++++++++++++ folly/IPAddressV6.h | 2 ++ folly/test/IPAddressTest.cpp | 16 ++++++++++++++++ 5 files changed, 43 insertions(+) diff --git a/folly/IPAddressV4.cpp b/folly/IPAddressV4.cpp index 6ca17864..ff44cee8 100644 --- a/folly/IPAddressV4.cpp +++ b/folly/IPAddressV4.cpp @@ -44,6 +44,15 @@ void toAppend(IPAddressV4 addr, fbstring* result) { result->append(addr.str()); } +bool IPAddressV4::validate(StringPiece ip) { + constexpr size_t kStrMaxLen = INET_ADDRSTRLEN; + std::array ip_cstr; + const size_t len = std::min(ip.size(), kStrMaxLen); + std::memcpy(ip_cstr.data(), ip.data(), len); + ip_cstr[len] = 0; + struct in_addr addr; + return 1 == inet_pton(AF_INET, ip_cstr.data(), &addr); +} // public static IPAddressV4 IPAddressV4::fromLong(uint32_t src) { diff --git a/folly/IPAddressV4.h b/folly/IPAddressV4.h index 462b371d..02c93114 100644 --- a/folly/IPAddressV4.h +++ b/folly/IPAddressV4.h @@ -53,6 +53,8 @@ typedef std::array ByteArray4; */ class IPAddressV4 : boost::totally_ordered { public: + static bool validate(StringPiece ip); + // create an IPAddressV4 instance from a uint32_t (network byte order) static IPAddressV4 fromLong(uint32_t src); // same as above but host byte order diff --git a/folly/IPAddressV6.cpp b/folly/IPAddressV6.cpp index 915767b4..d0927882 100644 --- a/folly/IPAddressV6.cpp +++ b/folly/IPAddressV6.cpp @@ -48,6 +48,20 @@ void toAppend(IPAddressV6 addr, fbstring* result) { result->append(addr.str()); } +bool IPAddressV6::validate(StringPiece ip) { + if (ip.size() > 0 && ip.front() == '[' && ip.back() == ']') { + ip = ip.subpiece(1, ip.size() - 2); + } + + constexpr size_t kStrMaxLen = INET6_ADDRSTRLEN; + std::array ip_cstr; + const size_t len = std::min(ip.size(), kStrMaxLen); + std::memcpy(ip_cstr.data(), ip.data(), len); + ip_cstr[len] = 0; + struct in6_addr addr; + return 1 == inet_pton(AF_INET6, ip_cstr.data(), &addr); +} + // public default constructor IPAddressV6::IPAddressV6() { } diff --git a/folly/IPAddressV6.h b/folly/IPAddressV6.h index 5a040455..be32b4aa 100644 --- a/folly/IPAddressV6.h +++ b/folly/IPAddressV6.h @@ -86,6 +86,8 @@ class IPAddressV6 : boost::totally_ordered { static constexpr size_t kToFullyQualifiedSize = 8 /*words*/ * 4 /*hex chars per word*/ + 7 /*separators*/; + static bool validate(StringPiece ip); + /** * Create a new IPAddress instance from the provided binary data. * @throws IPAddressFormatException if the input length is not 16 bytes. diff --git a/folly/test/IPAddressTest.cpp b/folly/test/IPAddressTest.cpp index 785a08c4..c9c6a8ad 100644 --- a/folly/test/IPAddressTest.cpp +++ b/folly/test/IPAddressTest.cpp @@ -219,6 +219,22 @@ TEST(IPAddress, CtorDefault) { EXPECT_EQ(IPAddressV6("::0"), v6); } +TEST(IPAddressV4, validate) { + EXPECT_TRUE(IPAddressV4::validate("0.0.0.0")); + EXPECT_FALSE(IPAddressV4::validate("0.0.0.")); + EXPECT_TRUE(IPAddressV4::validate("127.127.127.127")); +} + +TEST(IPAddressV6, validate) { + EXPECT_TRUE(IPAddressV6::validate("2620:0:1cfe:face:b00c::3")); + EXPECT_FALSE(IPAddressV6::validate("0.0.0.0")); + EXPECT_TRUE(IPAddressV6::validate("[2620:0:1cfe:face:b00c::3]")); + EXPECT_TRUE(IPAddressV6::validate("::ffff:0.1.1.1")); + EXPECT_TRUE(IPAddressV6::validate("2620:0000:1cfe:face:b00c:0000:0000:0003")); + EXPECT_TRUE( + IPAddressV6::validate("2620:0000:1cfe:face:b00c:0000:127.127.127.127")); +} + // Test addresses constructed using a in[6]_addr value TEST_P(IPAddressTest, CtorAddress) { AddressData param = GetParam(); -- 2.34.1