Browse Source

[2384] Better TTL range checking

Also check partial values and wrap-arouds for numbers.
Michal 'vorner' Vaner 12 years ago
parent
commit
0c55100a70
2 changed files with 28 additions and 0 deletions
  1. 11 0
      src/lib/dns/rrttl.cc
  2. 17 0
      src/lib/dns/tests/rrttl_unittest.cc

+ 11 - 0
src/lib/dns/rrttl.cc

@@ -98,6 +98,17 @@ RRTTL::RRTTL(const std::string& ttlstr) {
                                                                       unit));
             // Add what we found
             val += multiply * value;
+            // The partial value is still in range (the value can only grow,
+            // so if we get out now, it won't get better).
+            //
+            // Any valid uint32_t number must have at most 10 digits. If it
+            // has more, it could wrap around the int64_t silently (at least
+            // in theory, some compilers seem to throw from lexical_cast).
+            if (unit - pos > 10 || value <= 0 || val <= 0 ||
+                val >= 0xffffffff) {
+                isc_throw(InvalidRRTTL, "Part of TTL out of range: " <<
+                          ttlstr);
+            }
             // Move to after the unit (if any). But make sure not to increment
             // past end, which is, strictly speaking, illegal.
             pos = unit;

+ 17 - 0
src/lib/dns/tests/rrttl_unittest.cc

@@ -108,6 +108,23 @@ TEST_F(RRTTLTest, fromTextUnit) {
     // Awkward, but allowed case - the same unit used twice.
     EXPECT_EQ(20 * 3600, RRTTL("12H8H").getValue());
 
+    // Negative number in part of the expression, but the total is positive.
+    // Rejected.
+    EXPECT_THROW(RRTTL("-1S1H"), InvalidRRTTL);
+
+    // Some things out of range in the ttl, but it wraps to number in range
+    // in int64_t. Should still not get fooled and reject it.
+
+    // First part out of range
+    EXPECT_THROW(RRTTL("9223372036854775807S9223372036854775807S2S"),
+                 InvalidRRTTL);
+    // Second part out of range, but it immediately wraps (2S+2^64-2S)
+    EXPECT_THROW(RRTTL("2S18446744073709551614S"),
+                 InvalidRRTTL);
+    // The whole thing wraps right away (2^64S)
+    EXPECT_THROW(RRTTL("18446744073709551616S"),
+                 InvalidRRTTL);
+
     // Missing before unit.
     EXPECT_THROW(RRTTL("W5H"), InvalidRRTTL);
     EXPECT_THROW(RRTTL("5hW"), InvalidRRTTL);