resolv 0.3.0 → 0.3.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 +94 -11
- metadata +3 -14
- data/.github/dependabot.yml +0 -6
- data/.github/workflows/test.yml +0 -28
- data/.gitignore +0 -10
- data/Gemfile +0 -7
- data/Rakefile +0 -10
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/resolv.gemspec +0 -29
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 82cf1416dbd548bac4a243078cb8b93a0990f906169eff49752840d3145d0a0a
|
|
4
|
+
data.tar.gz: baf98405285dd3a553873a2f10e20d188e1e73cf066bf5f430b8d206c553978f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 646bccbb40a992224d079ddd8a586a231a69f67f628d424f79e1079dce4fcc346254ec0288d874ec356e199cfffb5c694b0cea8b51ed2435299a72ec29d88759
|
|
7
|
+
data.tar.gz: 28f34daddd2b5e3262e1b6b4381933c40683c8938129efad0914d495ae522f0c0b53bcbd6108073c1b3b1b4beb7f67d5e8af4b2af17387812c7275bed11c696d
|
data/lib/resolv.rb
CHANGED
|
@@ -37,7 +37,7 @@ end
|
|
|
37
37
|
|
|
38
38
|
class Resolv
|
|
39
39
|
|
|
40
|
-
VERSION = "0.3.
|
|
40
|
+
VERSION = "0.3.2"
|
|
41
41
|
|
|
42
42
|
##
|
|
43
43
|
# Looks up the first IP address for +name+.
|
|
@@ -1219,6 +1219,13 @@ class Resolv
|
|
|
1219
1219
|
|
|
1220
1220
|
class Str # :nodoc:
|
|
1221
1221
|
def initialize(string)
|
|
1222
|
+
# A label is limited to 63 octets. [RFC 1035 2.3.4] Checking it here
|
|
1223
|
+
# makes it an invariant of the object: every label, however it was
|
|
1224
|
+
# built, fits in its length octet and cannot wrap it. Callers turn
|
|
1225
|
+
# this into the error their own contract promises.
|
|
1226
|
+
if string.bytesize > 63
|
|
1227
|
+
raise ArgumentError, "DNS label is too long (#{string.bytesize} bytes, max 63): #{string.inspect}"
|
|
1228
|
+
end
|
|
1222
1229
|
@string = string
|
|
1223
1230
|
# case insensivity of DNS labels doesn't apply non-ASCII characters. [RFC 4343]
|
|
1224
1231
|
# This assumes @string is given in ASCII compatible encoding.
|
|
@@ -1264,7 +1271,26 @@ class Resolv
|
|
|
1264
1271
|
when Name
|
|
1265
1272
|
return arg
|
|
1266
1273
|
when String
|
|
1267
|
-
|
|
1274
|
+
# A hostname is runtime data rather than a programming mistake, so
|
|
1275
|
+
# both size limits surface as ResolvError to stay rescuable alongside
|
|
1276
|
+
# the rest of name resolution. The type check below is a caller
|
|
1277
|
+
# mistake and keeps raising ArgumentError.
|
|
1278
|
+
begin
|
|
1279
|
+
labels = Label.split(arg)
|
|
1280
|
+
rescue ArgumentError => e
|
|
1281
|
+
raise ResolvError.new(e.message)
|
|
1282
|
+
end
|
|
1283
|
+
# Label::Str enforces the per-label limit. Only the total is knowable
|
|
1284
|
+
# here, and it counts the encoded form, so size starts at 1 for the
|
|
1285
|
+
# root label's terminating zero octet. [RFC 1035 2.3.4, 3.1]
|
|
1286
|
+
size = 1
|
|
1287
|
+
labels.each do |label|
|
|
1288
|
+
size += 1 + label.string.bytesize
|
|
1289
|
+
if size > 255
|
|
1290
|
+
raise ResolvError.new("DNS name is too long (#{size} octets, max 255): #{arg.inspect}")
|
|
1291
|
+
end
|
|
1292
|
+
end
|
|
1293
|
+
return Name.new(labels, /\.\z/ =~ arg ? true : false)
|
|
1268
1294
|
else
|
|
1269
1295
|
raise ArgumentError.new("cannot interpret as DNS name: #{arg.inspect}")
|
|
1270
1296
|
end
|
|
@@ -1386,12 +1412,24 @@ class Resolv
|
|
|
1386
1412
|
@rd == other.rd &&
|
|
1387
1413
|
@ra == other.ra &&
|
|
1388
1414
|
@rcode == other.rcode &&
|
|
1389
|
-
|
|
1415
|
+
question_equal?(other.question) &&
|
|
1390
1416
|
@answer == other.answer &&
|
|
1391
1417
|
@authority == other.authority &&
|
|
1392
1418
|
@additional == other.additional
|
|
1393
1419
|
end
|
|
1394
1420
|
|
|
1421
|
+
# A question holds the resource class itself, and decoding creates a fresh
|
|
1422
|
+
# class for each unknown type, so the classes cannot be compared by
|
|
1423
|
+
# identity alone.
|
|
1424
|
+
private def question_equal?(other_question) # :nodoc:
|
|
1425
|
+
return false unless @question.length == other_question.length
|
|
1426
|
+
@question.zip(other_question) {|(name, typeclass), (o_name, o_typeclass)|
|
|
1427
|
+
return false unless name == o_name &&
|
|
1428
|
+
Resource::Generic.type_class_equal?(typeclass, o_typeclass)
|
|
1429
|
+
}
|
|
1430
|
+
return true
|
|
1431
|
+
end
|
|
1432
|
+
|
|
1395
1433
|
def add_question(name, typeclass)
|
|
1396
1434
|
@question << [Name.create(name), typeclass]
|
|
1397
1435
|
end
|
|
@@ -1498,8 +1536,15 @@ class Resolv
|
|
|
1498
1536
|
end
|
|
1499
1537
|
|
|
1500
1538
|
def put_string(d)
|
|
1501
|
-
|
|
1502
|
-
|
|
1539
|
+
s = d.to_s
|
|
1540
|
+
# A character-string is prefixed by a single length octet, so it can
|
|
1541
|
+
# hold at most 255 octets. [RFC 1035 3.3] Reject anything longer to
|
|
1542
|
+
# avoid silently truncating the length to its low 8 bits (mod 256).
|
|
1543
|
+
if s.bytesize > 255
|
|
1544
|
+
raise ArgumentError, "character-string is too long (#{s.bytesize} bytes, max 255): #{s.inspect}"
|
|
1545
|
+
end
|
|
1546
|
+
self.put_pack("C", s.bytesize)
|
|
1547
|
+
@data << s
|
|
1503
1548
|
end
|
|
1504
1549
|
|
|
1505
1550
|
def put_string_list(ds)
|
|
@@ -1529,7 +1574,17 @@ class Resolv
|
|
|
1529
1574
|
end
|
|
1530
1575
|
|
|
1531
1576
|
def put_label(d)
|
|
1532
|
-
|
|
1577
|
+
s = d.to_s
|
|
1578
|
+
# Label::Str applies this limit when a label is built, so what is left
|
|
1579
|
+
# for here is a raw string handed straight to put_labels. The two ways
|
|
1580
|
+
# an over-long label goes wrong differ: 64 to 255 octets write a length
|
|
1581
|
+
# octet in the reserved or compression pointer range, and 256 or more
|
|
1582
|
+
# wrap it mod 256. Either way the encoded name stops being the name the
|
|
1583
|
+
# caller asked for. [RFC 1035 2.3.4, 4.1.4]
|
|
1584
|
+
if s.bytesize > 63
|
|
1585
|
+
raise ArgumentError, "DNS label is too long (#{s.bytesize} bytes, max 63): #{s.inspect}"
|
|
1586
|
+
end
|
|
1587
|
+
self.put_string(s)
|
|
1533
1588
|
end
|
|
1534
1589
|
end
|
|
1535
1590
|
|
|
@@ -1655,6 +1710,9 @@ class Resolv
|
|
|
1655
1710
|
prev_index = @index
|
|
1656
1711
|
save_index = nil
|
|
1657
1712
|
d = []
|
|
1713
|
+
# size counts the encoded form, so it starts at 1 for the root
|
|
1714
|
+
# label's terminating zero octet. [RFC 1035 3.1]
|
|
1715
|
+
size = 1
|
|
1658
1716
|
while true
|
|
1659
1717
|
raise DecodeError.new("limit exceeded") if @limit <= @index
|
|
1660
1718
|
case @data.getbyte(@index)
|
|
@@ -1675,13 +1733,21 @@ class Resolv
|
|
|
1675
1733
|
end
|
|
1676
1734
|
@index = idx
|
|
1677
1735
|
else
|
|
1678
|
-
|
|
1736
|
+
l = self.get_label
|
|
1737
|
+
d << l
|
|
1738
|
+
size += 1 + l.string.bytesize
|
|
1739
|
+
raise DecodeError.new("name label data exceed 255 octets") if size > 255
|
|
1679
1740
|
end
|
|
1680
1741
|
end
|
|
1681
1742
|
end
|
|
1682
1743
|
|
|
1683
1744
|
def get_label
|
|
1684
1745
|
return Label::Str.new(self.get_string)
|
|
1746
|
+
rescue ArgumentError => e
|
|
1747
|
+
# A length octet of 64..191 is reserved rather than a label length,
|
|
1748
|
+
# but this decoder used to read it as one. [RFC 1035 4.1.4] Report it
|
|
1749
|
+
# the way the rest of a malformed message is reported.
|
|
1750
|
+
raise DecodeError.new(e.message)
|
|
1685
1751
|
end
|
|
1686
1752
|
|
|
1687
1753
|
def get_question
|
|
@@ -1870,8 +1936,9 @@ class Resolv
|
|
|
1870
1936
|
key_name = :"key#{key_number}"
|
|
1871
1937
|
c.const_set(:KeyName, key_name)
|
|
1872
1938
|
c.const_set(:KeyNumber, key_number)
|
|
1873
|
-
|
|
1874
|
-
|
|
1939
|
+
# Not registered in a constant or in ClassHash. ClassHash creates a
|
|
1940
|
+
# class for every unknown SvcParamKey, so registering them
|
|
1941
|
+
# permanently would let a malicious response exhaust memory.
|
|
1875
1942
|
return c
|
|
1876
1943
|
end
|
|
1877
1944
|
end
|
|
@@ -2169,12 +2236,28 @@ class Resolv
|
|
|
2169
2236
|
return self.new(msg.get_bytes)
|
|
2170
2237
|
end
|
|
2171
2238
|
|
|
2239
|
+
# create makes a fresh class for each decoded resource, so the type and
|
|
2240
|
+
# class values have to be compared instead of the class itself.
|
|
2241
|
+
def self.type_class_equal?(klass, other) # :nodoc:
|
|
2242
|
+
return true if klass.equal?(other)
|
|
2243
|
+
Generic > klass && Generic > other &&
|
|
2244
|
+
klass::TypeValue == other::TypeValue &&
|
|
2245
|
+
klass::ClassValue == other::ClassValue
|
|
2246
|
+
end
|
|
2247
|
+
|
|
2248
|
+
def ==(other) # :nodoc:
|
|
2249
|
+
return other.is_a?(Generic) &&
|
|
2250
|
+
Generic.type_class_equal?(self.class, other.class) &&
|
|
2251
|
+
@data == other.data
|
|
2252
|
+
end
|
|
2253
|
+
|
|
2172
2254
|
def self.create(type_value, class_value) # :nodoc:
|
|
2173
2255
|
c = Class.new(Generic)
|
|
2174
2256
|
c.const_set(:TypeValue, type_value)
|
|
2175
2257
|
c.const_set(:ClassValue, class_value)
|
|
2176
|
-
|
|
2177
|
-
|
|
2258
|
+
# Not registered in a constant or in ClassHash. get_class creates a
|
|
2259
|
+
# class for every unknown (type, class) pair, so registering them
|
|
2260
|
+
# permanently would let a malicious response exhaust memory.
|
|
2178
2261
|
return c
|
|
2179
2262
|
end
|
|
2180
2263
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: resolv
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tanaka Akira
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies: []
|
|
13
12
|
description: Thread-aware DNS resolver library in Ruby.
|
|
14
13
|
email:
|
|
@@ -17,17 +16,9 @@ executables: []
|
|
|
17
16
|
extensions: []
|
|
18
17
|
extra_rdoc_files: []
|
|
19
18
|
files:
|
|
20
|
-
- ".github/dependabot.yml"
|
|
21
|
-
- ".github/workflows/test.yml"
|
|
22
|
-
- ".gitignore"
|
|
23
|
-
- Gemfile
|
|
24
19
|
- LICENSE.txt
|
|
25
20
|
- README.md
|
|
26
|
-
- Rakefile
|
|
27
|
-
- bin/console
|
|
28
|
-
- bin/setup
|
|
29
21
|
- lib/resolv.rb
|
|
30
|
-
- resolv.gemspec
|
|
31
22
|
homepage: https://github.com/ruby/resolv
|
|
32
23
|
licenses:
|
|
33
24
|
- Ruby
|
|
@@ -35,7 +26,6 @@ licenses:
|
|
|
35
26
|
metadata:
|
|
36
27
|
homepage_uri: https://github.com/ruby/resolv
|
|
37
28
|
source_code_uri: https://github.com/ruby/resolv
|
|
38
|
-
post_install_message:
|
|
39
29
|
rdoc_options: []
|
|
40
30
|
require_paths:
|
|
41
31
|
- lib
|
|
@@ -50,8 +40,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
50
40
|
- !ruby/object:Gem::Version
|
|
51
41
|
version: '0'
|
|
52
42
|
requirements: []
|
|
53
|
-
rubygems_version: 3.
|
|
54
|
-
signing_key:
|
|
43
|
+
rubygems_version: 3.6.9
|
|
55
44
|
specification_version: 4
|
|
56
45
|
summary: Thread-aware DNS resolver library in Ruby.
|
|
57
46
|
test_files: []
|
data/.github/dependabot.yml
DELETED
data/.github/workflows/test.yml
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
name: test
|
|
2
|
-
|
|
3
|
-
on: [push, pull_request]
|
|
4
|
-
|
|
5
|
-
jobs:
|
|
6
|
-
ruby-versions:
|
|
7
|
-
uses: ruby/actions/.github/workflows/ruby_versions.yml@master
|
|
8
|
-
with:
|
|
9
|
-
engine: cruby
|
|
10
|
-
min_version: 2.5
|
|
11
|
-
|
|
12
|
-
build:
|
|
13
|
-
needs: ruby-versions
|
|
14
|
-
name: build (${{ matrix.ruby }} / ${{ matrix.os }})
|
|
15
|
-
strategy:
|
|
16
|
-
matrix:
|
|
17
|
-
ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
|
|
18
|
-
os: [ ubuntu-latest, macos-latest ]
|
|
19
|
-
runs-on: ${{ matrix.os }}
|
|
20
|
-
steps:
|
|
21
|
-
- uses: actions/checkout@v4
|
|
22
|
-
- name: Set up Ruby
|
|
23
|
-
uses: ruby/setup-ruby@v1
|
|
24
|
-
with:
|
|
25
|
-
ruby-version: ${{ matrix.ruby }}
|
|
26
|
-
bundler-cache: true
|
|
27
|
-
- name: Run test
|
|
28
|
-
run: bundle exec rake test
|
data/.gitignore
DELETED
data/Gemfile
DELETED
data/Rakefile
DELETED
data/bin/console
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
require "bundler/setup"
|
|
4
|
-
require "resolv"
|
|
5
|
-
|
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
|
8
|
-
|
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
10
|
-
# require "pry"
|
|
11
|
-
# Pry.start
|
|
12
|
-
|
|
13
|
-
require "irb"
|
|
14
|
-
IRB.start(__FILE__)
|
data/bin/setup
DELETED
data/resolv.gemspec
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
name = File.basename(__FILE__, ".gemspec")
|
|
2
|
-
version = ["lib", Array.new(name.count("-")+1).join("/")].find do |dir|
|
|
3
|
-
break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
|
|
4
|
-
/^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
|
|
5
|
-
end rescue nil
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
Gem::Specification.new do |spec|
|
|
9
|
-
spec.name = name
|
|
10
|
-
spec.version = version
|
|
11
|
-
spec.authors = ["Tanaka Akira"]
|
|
12
|
-
spec.email = ["akr@fsij.org"]
|
|
13
|
-
|
|
14
|
-
spec.summary = %q{Thread-aware DNS resolver library in Ruby.}
|
|
15
|
-
spec.description = %q{Thread-aware DNS resolver library in Ruby.}
|
|
16
|
-
spec.homepage = "https://github.com/ruby/resolv"
|
|
17
|
-
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
|
18
|
-
spec.licenses = ["Ruby", "BSD-2-Clause"]
|
|
19
|
-
|
|
20
|
-
spec.metadata["homepage_uri"] = spec.homepage
|
|
21
|
-
spec.metadata["source_code_uri"] = spec.homepage
|
|
22
|
-
|
|
23
|
-
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
|
24
|
-
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
25
|
-
end
|
|
26
|
-
spec.bindir = "exe"
|
|
27
|
-
spec.executables = []
|
|
28
|
-
spec.require_paths = ["lib"]
|
|
29
|
-
end
|