resolv 0.7.0 → 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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/resolv.rb +101 -13
  3. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2a32f99ca7eadc476467c7da9dbc5cfeb8152761da79306c91b21182141cbd44
4
- data.tar.gz: 2605e997fbe45d690ea5cdb82f7128a02fcb03d6b4150f2c6eea44747edb852a
3
+ metadata.gz: 38de4f14ddb183350d35593550caa34f9694644fb9d2fc79bd275d92d17ee338
4
+ data.tar.gz: 00d4977e89fb7cd8ec4a772c481d63e49fd4441b90c7ec5be42a79294ab3da19
5
5
  SHA512:
6
- metadata.gz: 4529d93d71f7139c6eb0a29c7c3d69d0817ad092b9bbb8a6718b8588c0fc43aec45c84db4e3684fb7320548a238c5122198812474d0bac8292ca0891fa687c91
7
- data.tar.gz: 9fcbff9a156782b6f5a8247262c237b3ba22c1843205a3ddc2d47b185e46fe959a2b62651b21c1573141748b35f8fe6063ab3c445f285d1990b35d1f129eaf44
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.0"
38
+ VERSION = "0.7.2"
39
39
 
40
40
  ##
41
41
  # Looks up the first IP address for +name+.
@@ -487,13 +487,18 @@ class Resolv
487
487
  # * Resolv::DNS::Resource::IN::A
488
488
  # * Resolv::DNS::Resource::IN::AAAA
489
489
  # * Resolv::DNS::Resource::IN::ANY
490
+ # * Resolv::DNS::Resource::IN::CAA
490
491
  # * Resolv::DNS::Resource::IN::CNAME
491
492
  # * Resolv::DNS::Resource::IN::HINFO
493
+ # * Resolv::DNS::Resource::IN::HTTPS
494
+ # * Resolv::DNS::Resource::IN::LOC
492
495
  # * Resolv::DNS::Resource::IN::MINFO
493
496
  # * Resolv::DNS::Resource::IN::MX
494
497
  # * Resolv::DNS::Resource::IN::NS
495
498
  # * Resolv::DNS::Resource::IN::PTR
496
499
  # * Resolv::DNS::Resource::IN::SOA
500
+ # * Resolv::DNS::Resource::IN::SRV
501
+ # * Resolv::DNS::Resource::IN::SVCB
497
502
  # * Resolv::DNS::Resource::IN::TXT
498
503
  # * Resolv::DNS::Resource::IN::WKS
499
504
  #
@@ -721,7 +726,8 @@ class Resolv
721
726
  begin
722
727
  reply, from = recv_reply(select_result[0])
723
728
  rescue Errno::ECONNREFUSED, # GNU/Linux, FreeBSD
724
- Errno::ECONNRESET # Windows
729
+ Errno::ECONNRESET, # Windows
730
+ EOFError
725
731
  # No name server running on the server?
726
732
  # Don't wait anymore.
727
733
  raise ResolvTimeout
@@ -930,8 +936,11 @@ class Resolv
930
936
  end
931
937
 
932
938
  def recv_reply(readable_socks)
933
- len = readable_socks[0].read(2).unpack('n')[0]
939
+ len_data = readable_socks[0].read(2)
940
+ raise EOFError if len_data.nil? || len_data.bytesize != 2
941
+ len = len_data.unpack('n')[0]
934
942
  reply = @socks[0].read(len)
943
+ raise EOFError if reply.nil? || reply.bytesize != len
935
944
  return reply, nil
936
945
  end
937
946
 
@@ -1244,6 +1253,13 @@ class Resolv
1244
1253
 
1245
1254
  class Str # :nodoc:
1246
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
1247
1263
  @string = string
1248
1264
  # case insensivity of DNS labels doesn't apply non-ASCII characters. [RFC 4343]
1249
1265
  # This assumes @string is given in ASCII compatible encoding.
@@ -1289,7 +1305,26 @@ class Resolv
1289
1305
  when Name
1290
1306
  return arg
1291
1307
  when String
1292
- return Name.new(Label.split(arg), /\.\z/ =~ arg ? true : false)
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)
1293
1328
  else
1294
1329
  raise ArgumentError.new("cannot interpret as DNS name: #{arg.inspect}")
1295
1330
  end
@@ -1411,12 +1446,24 @@ class Resolv
1411
1446
  @rd == other.rd &&
1412
1447
  @ra == other.ra &&
1413
1448
  @rcode == other.rcode &&
1414
- @question == other.question &&
1449
+ question_equal?(other.question) &&
1415
1450
  @answer == other.answer &&
1416
1451
  @authority == other.authority &&
1417
1452
  @additional == other.additional
1418
1453
  end
1419
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
+
1420
1467
  def add_question(name, typeclass)
1421
1468
  @question << [Name.create(name), typeclass]
1422
1469
  end
@@ -1523,8 +1570,15 @@ class Resolv
1523
1570
  end
1524
1571
 
1525
1572
  def put_string(d)
1526
- self.put_pack("C", d.length)
1527
- @data << d
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
1528
1582
  end
1529
1583
 
1530
1584
  def put_string_list(ds)
@@ -1554,7 +1608,17 @@ class Resolv
1554
1608
  end
1555
1609
 
1556
1610
  def put_label(d)
1557
- self.put_string(d.to_s)
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)
1558
1622
  end
1559
1623
  end
1560
1624
 
@@ -1680,7 +1744,9 @@ class Resolv
1680
1744
  prev_index = @index
1681
1745
  save_index = nil
1682
1746
  d = []
1683
- size = -1
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
1684
1750
  while true
1685
1751
  raise DecodeError.new("limit exceeded") if @limit <= @index
1686
1752
  case @data.getbyte(@index)
@@ -1711,6 +1777,11 @@ class Resolv
1711
1777
 
1712
1778
  def get_label
1713
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)
1714
1785
  end
1715
1786
 
1716
1787
  def get_question
@@ -1898,8 +1969,9 @@ class Resolv
1898
1969
  key_name = :"key#{key_number}"
1899
1970
  c.const_set(:KeyName, key_name)
1900
1971
  c.const_set(:KeyNumber, key_number)
1901
- self.const_set(:"Key#{key_number}", c)
1902
- ClassHash[key_name] = ClassHash[key_number] = c
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.
1903
1975
  return c
1904
1976
  end
1905
1977
  end
@@ -2206,12 +2278,28 @@ class Resolv
2206
2278
  return self.new(msg.get_bytes)
2207
2279
  end
2208
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
+
2209
2296
  def self.create(type_value, class_value) # :nodoc:
2210
2297
  c = Class.new(Generic)
2211
2298
  c.const_set(:TypeValue, type_value)
2212
2299
  c.const_set(:ClassValue, class_value)
2213
- Generic.const_set("Type#{type_value}_Class#{class_value}", c)
2214
- ClassHash[[type_value, class_value]] = c
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.
2215
2303
  return c
2216
2304
  end
2217
2305
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resolv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tanaka Akira