resolv 0.7.1 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/resolv.rb +90 -11
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 38de4f14ddb183350d35593550caa34f9694644fb9d2fc79bd275d92d17ee338
|
|
4
|
+
data.tar.gz: 00d4977e89fb7cd8ec4a772c481d63e49fd4441b90c7ec5be42a79294ab3da19
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 175ca63aa1f82ebabc499bbcd8eedf17c33ff220c439187a1c5778ca2e74926d15651a720c0bb5f615a698747252d8f9cd82c5db5fb25d28a4d1e63cb696acf1
|
|
7
|
+
data.tar.gz: 8789721febc5b7a96a8bcfdc51dd503afefa648a6d7057e6951b77d1fb514c613e35524ef9680e4ef6d4ad49e310a0fa2d1e92a972eae0e8f23969519c7db1d9
|
data/lib/resolv.rb
CHANGED
|
@@ -35,7 +35,7 @@ require 'rbconfig'
|
|
|
35
35
|
class Resolv
|
|
36
36
|
|
|
37
37
|
# The version string
|
|
38
|
-
VERSION = "0.7.
|
|
38
|
+
VERSION = "0.7.2"
|
|
39
39
|
|
|
40
40
|
##
|
|
41
41
|
# Looks up the first IP address for +name+.
|
|
@@ -1253,6 +1253,13 @@ class Resolv
|
|
|
1253
1253
|
|
|
1254
1254
|
class Str # :nodoc:
|
|
1255
1255
|
def initialize(string)
|
|
1256
|
+
# A label is limited to 63 octets. [RFC 1035 2.3.4] Checking it here
|
|
1257
|
+
# makes it an invariant of the object: every label, however it was
|
|
1258
|
+
# built, fits in its length octet and cannot wrap it. Callers turn
|
|
1259
|
+
# this into the error their own contract promises.
|
|
1260
|
+
if string.bytesize > 63
|
|
1261
|
+
raise ArgumentError, "DNS label is too long (#{string.bytesize} bytes, max 63): #{string.inspect}"
|
|
1262
|
+
end
|
|
1256
1263
|
@string = string
|
|
1257
1264
|
# case insensivity of DNS labels doesn't apply non-ASCII characters. [RFC 4343]
|
|
1258
1265
|
# This assumes @string is given in ASCII compatible encoding.
|
|
@@ -1298,7 +1305,26 @@ class Resolv
|
|
|
1298
1305
|
when Name
|
|
1299
1306
|
return arg
|
|
1300
1307
|
when String
|
|
1301
|
-
|
|
1308
|
+
# A hostname is runtime data rather than a programming mistake, so
|
|
1309
|
+
# both size limits surface as ResolvError to stay rescuable alongside
|
|
1310
|
+
# the rest of name resolution. The type check below is a caller
|
|
1311
|
+
# mistake and keeps raising ArgumentError.
|
|
1312
|
+
begin
|
|
1313
|
+
labels = Label.split(arg)
|
|
1314
|
+
rescue ArgumentError => e
|
|
1315
|
+
raise ResolvError.new(e.message)
|
|
1316
|
+
end
|
|
1317
|
+
# Label::Str enforces the per-label limit. Only the total is knowable
|
|
1318
|
+
# here, and it counts the encoded form, so size starts at 1 for the
|
|
1319
|
+
# root label's terminating zero octet. [RFC 1035 2.3.4, 3.1]
|
|
1320
|
+
size = 1
|
|
1321
|
+
labels.each do |label|
|
|
1322
|
+
size += 1 + label.string.bytesize
|
|
1323
|
+
if size > 255
|
|
1324
|
+
raise ResolvError.new("DNS name is too long (#{size} octets, max 255): #{arg.inspect}")
|
|
1325
|
+
end
|
|
1326
|
+
end
|
|
1327
|
+
return Name.new(labels, /\.\z/ =~ arg ? true : false)
|
|
1302
1328
|
else
|
|
1303
1329
|
raise ArgumentError.new("cannot interpret as DNS name: #{arg.inspect}")
|
|
1304
1330
|
end
|
|
@@ -1420,12 +1446,24 @@ class Resolv
|
|
|
1420
1446
|
@rd == other.rd &&
|
|
1421
1447
|
@ra == other.ra &&
|
|
1422
1448
|
@rcode == other.rcode &&
|
|
1423
|
-
|
|
1449
|
+
question_equal?(other.question) &&
|
|
1424
1450
|
@answer == other.answer &&
|
|
1425
1451
|
@authority == other.authority &&
|
|
1426
1452
|
@additional == other.additional
|
|
1427
1453
|
end
|
|
1428
1454
|
|
|
1455
|
+
# A question holds the resource class itself, and decoding creates a fresh
|
|
1456
|
+
# class for each unknown type, so the classes cannot be compared by
|
|
1457
|
+
# identity alone.
|
|
1458
|
+
private def question_equal?(other_question) # :nodoc:
|
|
1459
|
+
return false unless @question.length == other_question.length
|
|
1460
|
+
@question.zip(other_question) {|(name, typeclass), (o_name, o_typeclass)|
|
|
1461
|
+
return false unless name == o_name &&
|
|
1462
|
+
Resource::Generic.type_class_equal?(typeclass, o_typeclass)
|
|
1463
|
+
}
|
|
1464
|
+
return true
|
|
1465
|
+
end
|
|
1466
|
+
|
|
1429
1467
|
def add_question(name, typeclass)
|
|
1430
1468
|
@question << [Name.create(name), typeclass]
|
|
1431
1469
|
end
|
|
@@ -1532,8 +1570,15 @@ class Resolv
|
|
|
1532
1570
|
end
|
|
1533
1571
|
|
|
1534
1572
|
def put_string(d)
|
|
1535
|
-
|
|
1536
|
-
|
|
1573
|
+
s = d.to_s
|
|
1574
|
+
# A character-string is prefixed by a single length octet, so it can
|
|
1575
|
+
# hold at most 255 octets. [RFC 1035 3.3] Reject anything longer to
|
|
1576
|
+
# avoid silently truncating the length to its low 8 bits (mod 256).
|
|
1577
|
+
if s.bytesize > 255
|
|
1578
|
+
raise ArgumentError, "character-string is too long (#{s.bytesize} bytes, max 255): #{s.inspect}"
|
|
1579
|
+
end
|
|
1580
|
+
self.put_pack("C", s.bytesize)
|
|
1581
|
+
@data << s
|
|
1537
1582
|
end
|
|
1538
1583
|
|
|
1539
1584
|
def put_string_list(ds)
|
|
@@ -1563,7 +1608,17 @@ class Resolv
|
|
|
1563
1608
|
end
|
|
1564
1609
|
|
|
1565
1610
|
def put_label(d)
|
|
1566
|
-
|
|
1611
|
+
s = d.to_s
|
|
1612
|
+
# Label::Str applies this limit when a label is built, so what is left
|
|
1613
|
+
# for here is a raw string handed straight to put_labels. The two ways
|
|
1614
|
+
# an over-long label goes wrong differ: 64 to 255 octets write a length
|
|
1615
|
+
# octet in the reserved or compression pointer range, and 256 or more
|
|
1616
|
+
# wrap it mod 256. Either way the encoded name stops being the name the
|
|
1617
|
+
# caller asked for. [RFC 1035 2.3.4, 4.1.4]
|
|
1618
|
+
if s.bytesize > 63
|
|
1619
|
+
raise ArgumentError, "DNS label is too long (#{s.bytesize} bytes, max 63): #{s.inspect}"
|
|
1620
|
+
end
|
|
1621
|
+
self.put_string(s)
|
|
1567
1622
|
end
|
|
1568
1623
|
end
|
|
1569
1624
|
|
|
@@ -1689,7 +1744,9 @@ class Resolv
|
|
|
1689
1744
|
prev_index = @index
|
|
1690
1745
|
save_index = nil
|
|
1691
1746
|
d = []
|
|
1692
|
-
size
|
|
1747
|
+
# size counts the encoded form, so it starts at 1 for the root
|
|
1748
|
+
# label's terminating zero octet. [RFC 1035 3.1]
|
|
1749
|
+
size = 1
|
|
1693
1750
|
while true
|
|
1694
1751
|
raise DecodeError.new("limit exceeded") if @limit <= @index
|
|
1695
1752
|
case @data.getbyte(@index)
|
|
@@ -1720,6 +1777,11 @@ class Resolv
|
|
|
1720
1777
|
|
|
1721
1778
|
def get_label
|
|
1722
1779
|
return Label::Str.new(self.get_string)
|
|
1780
|
+
rescue ArgumentError => e
|
|
1781
|
+
# A length octet of 64..191 is reserved rather than a label length,
|
|
1782
|
+
# but this decoder used to read it as one. [RFC 1035 4.1.4] Report it
|
|
1783
|
+
# the way the rest of a malformed message is reported.
|
|
1784
|
+
raise DecodeError.new(e.message)
|
|
1723
1785
|
end
|
|
1724
1786
|
|
|
1725
1787
|
def get_question
|
|
@@ -1907,8 +1969,9 @@ class Resolv
|
|
|
1907
1969
|
key_name = :"key#{key_number}"
|
|
1908
1970
|
c.const_set(:KeyName, key_name)
|
|
1909
1971
|
c.const_set(:KeyNumber, key_number)
|
|
1910
|
-
|
|
1911
|
-
|
|
1972
|
+
# Not registered in a constant or in ClassHash. ClassHash creates a
|
|
1973
|
+
# class for every unknown SvcParamKey, so registering them
|
|
1974
|
+
# permanently would let a malicious response exhaust memory.
|
|
1912
1975
|
return c
|
|
1913
1976
|
end
|
|
1914
1977
|
end
|
|
@@ -2215,12 +2278,28 @@ class Resolv
|
|
|
2215
2278
|
return self.new(msg.get_bytes)
|
|
2216
2279
|
end
|
|
2217
2280
|
|
|
2281
|
+
# create makes a fresh class for each decoded resource, so the type and
|
|
2282
|
+
# class values have to be compared instead of the class itself.
|
|
2283
|
+
def self.type_class_equal?(klass, other) # :nodoc:
|
|
2284
|
+
return true if klass.equal?(other)
|
|
2285
|
+
Generic > klass && Generic > other &&
|
|
2286
|
+
klass::TypeValue == other::TypeValue &&
|
|
2287
|
+
klass::ClassValue == other::ClassValue
|
|
2288
|
+
end
|
|
2289
|
+
|
|
2290
|
+
def ==(other) # :nodoc:
|
|
2291
|
+
return other.is_a?(Generic) &&
|
|
2292
|
+
Generic.type_class_equal?(self.class, other.class) &&
|
|
2293
|
+
@data == other.data
|
|
2294
|
+
end
|
|
2295
|
+
|
|
2218
2296
|
def self.create(type_value, class_value) # :nodoc:
|
|
2219
2297
|
c = Class.new(Generic)
|
|
2220
2298
|
c.const_set(:TypeValue, type_value)
|
|
2221
2299
|
c.const_set(:ClassValue, class_value)
|
|
2222
|
-
|
|
2223
|
-
|
|
2300
|
+
# Not registered in a constant or in ClassHash. get_class creates a
|
|
2301
|
+
# class for every unknown (type, class) pair, so registering them
|
|
2302
|
+
# permanently would let a malicious response exhaust memory.
|
|
2224
2303
|
return c
|
|
2225
2304
|
end
|
|
2226
2305
|
end
|