]> granicus.if.org Git - pdns/commitdiff
Throw is serial won't fit into uint32_t, fixes #1009
authorAki Tuomi <cmouse@desteem.org>
Mon, 3 Nov 2014 20:08:58 +0000 (22:08 +0200)
committerAki Tuomi <cmouse@desteem.org>
Tue, 4 Nov 2014 08:34:20 +0000 (10:34 +0200)
pdns/dns.cc
pdns/misc.cc
pdns/misc.hh
pdns/rcpgenerator.cc
pdns/test-dnsrecords_cc.cc

index 1b0b30984bfc6be2178d10098089e49f07fdae2b..d1683519217ce3f9891c06bcfcb419cc5a742185 100644 (file)
@@ -197,7 +197,8 @@ void fillSOAData(const string &content, SOAData &data)
   if(pleft>1) 
     data.hostmaster=attodot(parts[1]); // ahu@ds9a.nl -> ahu.ds9a.nl, piet.puk@ds9a.nl -> piet\.puk.ds9a.nl
 
-  data.serial = pleft > 2 ? strtoul(parts[2].c_str(), NULL, 10) : 0;
+  data.serial = pleft > 2 ? strtoui(parts[2].c_str(), NULL, 10) : 0;
+  if (data.serial == UINT_MAX && errno == ERANGE) throw PDNSException("serial number too large in '"+parts[2]+"'");
 
   data.refresh = pleft > 3 ? atoi(parts[3].c_str())
         : ::arg().asNum("soa-refresh-default");
index 5f28dc966e522c249f64b4fae03e689aa2537bd6..bc063f66da73316473486f7628bbd3d10b1344b2 100644 (file)
@@ -916,3 +916,14 @@ void setSocketTimestamps(int fd)
     L<<Logger::Error<<"Warning: unable to enable timestamp reporting for socket"<<endl;
 #endif
 }
+
+uint32_t strtoui(const char *nptr, char **endptr, int base)
+{
+  unsigned long val = strtoul(nptr, endptr, base);
+  if (val > UINT_MAX) {
+   errno = ERANGE;
+   return UINT_MAX;
+  } 
+
+  return val;
+}
index ea8906878b2774754abdc211325c7e69662831c2..d760f6b9a8b0c40e1fbf6edcd5e89d6e2a5b5d5e 100644 (file)
@@ -25,6 +25,7 @@
 #include <cstring>
 #include <cstdio>
 #include <regex.h>
+#include <limits.h>
 #include <boost/algorithm/string.hpp>
 #include <boost/multi_index_container.hpp>
 #include <boost/multi_index/ordered_index.hpp>
@@ -86,6 +87,8 @@ uint16_t getShort(const unsigned char *p);
 uint16_t getShort(const char *p);
 uint32_t getLong(const unsigned char *p);
 uint32_t getLong(const char *p);
+uint32_t strtoui(const char *nptr, char **endptr, int base);
+
 int logFacilityToLOG(unsigned int facility);
 
 struct ServiceTuple
index 4db2ae61201905c63aba2d89a29da6791fc81839..a5b04c4e5d76b433244a1af5d5738ef42a194219 100644 (file)
@@ -62,7 +62,8 @@ void RecordTextReader::xfr32BitInt(uint32_t &val)
     throw RecordTextException("expected digits at position "+lexical_cast<string>(d_pos)+" in '"+d_string+"'");
 
   char *endptr;
-  unsigned long ret=strtoul(d_string.c_str() + d_pos, &endptr, 10);
+  unsigned long ret=strtoui(d_string.c_str() + d_pos, &endptr, 10);
+  if (ret == UINT_MAX && errno == ERANGE) throw RecordTextException("serial number too large in '"+d_string+"'");
   val=ret;
   
   d_pos = endptr - d_string.c_str();
index 8f4ed24fe699d437844c5febb72d0e9830f6d6f5..37e7612a1637ae8cebc809bb909d4deef59dd8a3 100644 (file)
@@ -225,6 +225,7 @@ BOOST_AUTO_TEST_CASE(test_record_types_bad_values) {
      (case_t(QType::AAAA, "23:00::15::43", zone, false)) // double compression
      (case_t(QType::AAAA, "2a23:00::15::", zone, false)) // ditto 
      (case_t(QType::AAAA, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff", zone, false)) // truncated wire value
+     (case_t(QType::SOA, "ns.rec.test hostmaster.test.rec 20130512010 3600 3600 604800 120", zone, false)) // too long serial
 ;
 
   int n=0;