]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Fix negative port detection for IPv6 addresses on 32-bit 4911/head
authorRemi Gacogne <remi.gacogne@powerdns.com>
Sun, 15 Jan 2017 20:45:27 +0000 (21:45 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Sun, 15 Jan 2017 20:45:27 +0000 (21:45 +0100)
On a 32-bit Arch, our `test_ComboAddress` unit test fails because
`ComboAddress("[::1]:-6")` is considered valid. This is caused by
`stoul()` not throwing for a negative value and returning an `unsigned
long` value using unsigned integer wraparound rules. Since we used to
store the result value in a `signed int` and treat negative values
as if the port was not set, the test failed.

pdns/misc.cc

index 10912ff4f67bd0d7a8121d301ee4eaabdef291be..c80b4d5855aa4bc274d44a772798a701de83d15e 100644 (file)
@@ -710,7 +710,8 @@ int makeIPv6sockaddr(const std::string& addr, struct sockaddr_in6* ret)
   if(addr.empty())
     return -1;
   string ourAddr(addr);
-  int port = -1;
+  bool portSet = false;
+  unsigned int port;
   if(addr[0]=='[') { // [::]:53 style address
     string::size_type pos = addr.find(']');
     if(pos == string::npos || pos + 2 > addr.size() || addr[pos+1]!=':')
@@ -718,6 +719,7 @@ int makeIPv6sockaddr(const std::string& addr, struct sockaddr_in6* ret)
     ourAddr.assign(addr.c_str() + 1, pos-1);
     try {
       port = pdns_stou(addr.substr(pos+2));
+      portSet = true;
     }
     catch(std::out_of_range) {
       return -1;
@@ -744,12 +746,12 @@ int makeIPv6sockaddr(const std::string& addr, struct sockaddr_in6* ret)
     freeaddrinfo(res);
   }
 
-  if(port > 65535)
-    // negative ports are found with the pdns_stou above
-    return -1;
+  if(portSet) {
+    if(port > 65535)
+      return -1;
 
-  if(port >= 0)
     ret->sin6_port = htons(port);
+  }
 
   return 0;
 }