IPAddressV[46]::validate
authorYedidya Feldblum <yfeldblum@fb.com>
Tue, 29 Mar 2016 19:53:16 +0000 (12:53 -0700)
committerFacebook Github Bot 1 <facebook-github-bot-1-bot@fb.com>
Tue, 29 Mar 2016 20:05:24 +0000 (13:05 -0700)
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
folly/IPAddressV4.h
folly/IPAddressV6.cpp
folly/IPAddressV6.h
folly/test/IPAddressTest.cpp

index 6ca17864642e492e47975245db02c3d27eeb7147..ff44cee80acca2f9096e20c0cd1254f21b21fbf5 100644 (file)
@@ -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<char, kStrMaxLen + 1> 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) {
index 462b371d700ae932c1227f889f032840236d0484..02c93114f25703940cead58730d5ef6accd4578b 100644 (file)
@@ -53,6 +53,8 @@ typedef std::array<uint8_t, 4> ByteArray4;
  */
 class IPAddressV4 : boost::totally_ordered<IPAddressV4> {
  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
index 915767b493d9a620b21e89780ee203150eac3c9a..d092788270da7eb4f8590e9c99ca38300e231017 100644 (file)
@@ -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<char, kStrMaxLen + 1> 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() {
 }
index 5a040455161af73bd381bf0184d3bd233e0f6077..be32b4aaaedcb67137593ad45dac018a4c0b719c 100644 (file)
@@ -86,6 +86,8 @@ class IPAddressV6 : boost::totally_ordered<IPAddressV6> {
   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.
index 785a08c4eb12b588f10cedefcbd9383cc7a3558d..c9c6a8ad46ad32b56c6e0cc73149c22ef089fafc 100644 (file)
@@ -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();