uri-whatwg_parser 0.3.1 → 0.3.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 340c89cc9b0c80699547d7daa0a33c3c081250ebee1dd1178a36ee288a484a22
4
- data.tar.gz: 961034f93393490c76ad015aea1524b27b5955ef38112892d50b2a1e15a3ac50
3
+ metadata.gz: 21b70ae0fff882053d71cb5449b278d4e7b32f16933433f9425903f83c12305d
4
+ data.tar.gz: a51ae685b0cb8a7db1adb9f05f656be83e60e0da62c6eca0438872ca046debd8
5
5
  SHA512:
6
- metadata.gz: 987525847dbe6f04d4a2a4c3c8e338d57ebd964d4312528bc16e5e515ba7460922c3fedf08a4151227dbd1fbca11be4af38db6db53e1d741992460fd89c86bd0
7
- data.tar.gz: 12eae3fe44a8136aa66a55d1aa7e12b172980ae96470f890e34e721fae4c1f3f23155ff1a2e1db305ce2f239cdf239a7db43fe5feb153eb11f3f230c09fd77a4
6
+ metadata.gz: 905506fad119c654dc873129f8854431c9260b880de07b154b8ae45bd88b7bc4787a186236ae68ccf21af840c51a22bb84558a5651bb17e7070b166a222a96e0
7
+ data.tar.gz: 5e5cc0503cf20d6f5eb7fad89bdb60336516c8a83df9fe64715b84af77dcf50caf721ca7f36b31926a6a261ae6f824868a0d13f5892ee3b49b2a34a210a30078
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ ## Unreleased
2
+
3
+ ## 0.3.3
4
+
5
+ * Fix parsing an IPv4 address embedded in an IPv6 address with leading zeroes and non-decimal numbers
6
+ * Fix parsing an IPv6 address to reject a trailing `:`
7
+
8
+ ## 0.3.2
9
+
10
+ * Fix domain-to-ASCII process on host parsing to follow the latest spec
11
+
1
12
  ## 0.3.1
2
13
 
3
14
  * Fix a bug of parsing Windows drive letter
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # URI::WhatwgParser
2
2
  Ruby implementation of the [WHATWG URL Living Standard](https://url.spec.whatwg.org/).
3
3
 
4
- The latest revision that this package implements of the standard is [14 April 2026](https://url.spec.whatwg.org/commit-snapshots/b11d73b8caefe90403afe19210db05acba897722/)
4
+ The latest revision that this package implements of the standard is [18 August 2026](https://url.spec.whatwg.org/commit-snapshots/55d6699373ba68a16ec182f34222a74ed8bc3dac/)
5
5
 
6
6
  ## Installation
7
7
 
@@ -77,6 +77,7 @@ class URI::WhatwgParser
77
77
  if chars[i] == ":"
78
78
  raise ParseError, "invalid IPv6 format" unless chars[i + 1] == ":"
79
79
  i += 2
80
+ piece_index += 1
80
81
  compress = piece_index
81
82
  end
82
83
 
@@ -86,6 +87,7 @@ class URI::WhatwgParser
86
87
  if chars[i] == ":"
87
88
  raise ParseError, "invalid IPv6 format" if compress
88
89
  i += 1
90
+ piece_index += 1
89
91
  compress = piece_index
90
92
  next
91
93
  end
@@ -99,18 +101,9 @@ class URI::WhatwgParser
99
101
  end
100
102
 
101
103
  if chars[i] == "."
102
- # IPv4-mapped address must be valid and complete, no trailing dot
103
- ipv4_piece = chars[i - length, chars.length - (i - length)].join
104
- parts = ipv4_piece.split(".")
105
- if parts.length != 4 || parts.any? { |p| p.empty? } || ipv4_piece.end_with?(".")
106
- raise ParseError, "invalid IPv6 format"
107
- end
104
+ raise ParseError, "invalid IPv6 format" if length == 0 || piece_index > 6
108
105
 
109
- ipv4 = parse_ipv4(ipv4_piece)
110
- address[piece_index] = (ipv4 >> 16) & 0xFFFF
111
- address[piece_index + 1] = ipv4 & 0xFFFF
112
- piece_index += 2
113
- i = chars.length
106
+ piece_index = parse_embedded_ipv4(chars, i - length, address, piece_index)
114
107
  break
115
108
  end
116
109
 
@@ -119,21 +112,16 @@ class URI::WhatwgParser
119
112
  address[piece_index] = value
120
113
  piece_index += 1
121
114
 
122
- if i < chars.length
123
- if chars[i] == ":"
124
- i += 1
125
- elsif chars[i] != nil
126
- raise ParseError, "invalid IPv6 format"
127
- end
115
+ if chars[i] == ":"
116
+ i += 1
117
+ raise ParseError, "invalid IPv6 format" unless chars[i]
118
+ elsif chars[i]
119
+ raise ParseError, "invalid IPv6 format"
128
120
  end
129
121
  end
130
122
 
131
123
  if compress
132
- swaps = piece_index - compress
133
- (0...swaps).each do |j|
134
- address[7 - j] = address[compress + swaps - 1 - j]
135
- address[compress + swaps - 1 - j] = 0
136
- end
124
+ expand_ipv6_compression(address, compress, piece_index)
137
125
  elsif piece_index != 8
138
126
  raise ParseError, "invalid IPv6 format"
139
127
  end
@@ -141,6 +129,52 @@ class URI::WhatwgParser
141
129
  compress_ipv6(address)
142
130
  end
143
131
 
132
+ def parse_embedded_ipv4(chars, i, address, piece_index)
133
+ numbers_seen = 0
134
+
135
+ while i < chars.length
136
+ if numbers_seen > 0
137
+ raise ParseError, "invalid IPv6 format" unless chars[i] == "." && numbers_seen < 4
138
+ i += 1
139
+ end
140
+
141
+ raise ParseError, "invalid IPv6 format" unless chars[i]&.match?(/[0-9]/)
142
+
143
+ ipv4_piece = nil
144
+ while chars[i]&.match?(/[0-9]/)
145
+ number = chars[i].to_i
146
+ if ipv4_piece.nil?
147
+ ipv4_piece = number
148
+ elsif ipv4_piece == 0
149
+ raise ParseError, "invalid IPv6 format"
150
+ else
151
+ ipv4_piece = ipv4_piece * 10 + number
152
+ end
153
+ raise ParseError, "invalid IPv6 format" if ipv4_piece > 255
154
+ i += 1
155
+ end
156
+
157
+ address[piece_index] = address[piece_index] * 256 + ipv4_piece
158
+ numbers_seen += 1
159
+ piece_index += 1 if numbers_seen == 2 || numbers_seen == 4
160
+ end
161
+
162
+ raise ParseError, "invalid IPv6 format" if numbers_seen != 4
163
+
164
+ piece_index
165
+ end
166
+
167
+ def expand_ipv6_compression(address, compress, piece_index)
168
+ swaps = piece_index - compress
169
+ piece_index = 7
170
+
171
+ while piece_index != 0 && swaps > 0
172
+ address[piece_index], address[compress + swaps - 1] = address[compress + swaps - 1], address[piece_index]
173
+ piece_index -= 1
174
+ swaps -= 1
175
+ end
176
+ end
177
+
144
178
  def compress_ipv6(address)
145
179
  # Find the longest run of zeros for '::' compression
146
180
  best_base = nil
@@ -259,7 +293,13 @@ class URI::WhatwgParser
259
293
  return domain
260
294
  end
261
295
 
262
- ascii_domain = URI::IDNA.whatwg_to_ascii(domain.force_encoding(Encoding::UTF_8), be_strict: false)
296
+ begin
297
+ ascii_domain = URI::IDNA.whatwg_to_ascii(domain.force_encoding(Encoding::UTF_8), be_strict: false)
298
+ rescue URI::IDNA::Error, Encoding::CompatibilityError, ArgumentError
299
+ raise ParseError, "invalid host value" unless domain.ascii_only?
300
+
301
+ ascii_domain = domain.downcase
302
+ end
263
303
 
264
304
  raise ParseError, "including invalid value in host" if include_forbidden_domain_code_point?(ascii_domain)
265
305
  raise ParseError, "host can't be empty" if ascii_domain.empty?
@@ -2,6 +2,6 @@
2
2
 
3
3
  module URI
4
4
  class WhatwgParser
5
- VERSION = "0.3.1"
5
+ VERSION = "0.3.3"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uri-whatwg_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuji Yaginuma
@@ -73,7 +73,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
73
  - !ruby/object:Gem::Version
74
74
  version: '0'
75
75
  requirements: []
76
- rubygems_version: 4.0.10
76
+ rubygems_version: 4.0.16
77
77
  specification_version: 4
78
78
  summary: Ruby implementation of the WHATWG URL Living Standard
79
79
  test_files: []