Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check Encodings before calling force_encoding in Addressable::URI #341

Merged
merged 7 commits into from Aug 18, 2022
40 changes: 20 additions & 20 deletions lib/addressable/uri.rb
Expand Up @@ -899,7 +899,7 @@ def normalized_scheme
end
end
# All normalized values should be UTF-8
@normalized_scheme.force_encoding(Encoding::UTF_8) if @normalized_scheme
force_utf8_encoding_if_needed(@normalized_scheme)
@normalized_scheme
end

Expand Down Expand Up @@ -954,7 +954,7 @@ def normalized_user
end
end
# All normalized values should be UTF-8
@normalized_user.force_encoding(Encoding::UTF_8) if @normalized_user
force_utf8_encoding_if_needed(@normalized_user)
@normalized_user
end

Expand Down Expand Up @@ -1011,9 +1011,7 @@ def normalized_password
end
end
# All normalized values should be UTF-8
if @normalized_password
@normalized_password.force_encoding(Encoding::UTF_8)
end
force_utf8_encoding_if_needed(@normalized_password)
@normalized_password
end

Expand Down Expand Up @@ -1081,9 +1079,7 @@ def normalized_userinfo
end
end
# All normalized values should be UTF-8
if @normalized_userinfo
@normalized_userinfo.force_encoding(Encoding::UTF_8)
end
force_utf8_encoding_if_needed(@normalized_userinfo)
@normalized_userinfo
end

Expand Down Expand Up @@ -1150,9 +1146,7 @@ def normalized_host
end
end
# All normalized values should be UTF-8
if @normalized_host && !@normalized_host.empty?
@normalized_host.force_encoding(Encoding::UTF_8)
end
force_utf8_encoding_if_needed(@normalized_host)
@normalized_host
end

Expand Down Expand Up @@ -1270,9 +1264,7 @@ def normalized_authority
authority
end
# All normalized values should be UTF-8
if @normalized_authority
@normalized_authority.force_encoding(Encoding::UTF_8)
end
force_utf8_encoding_if_needed(@normalized_authority)
@normalized_authority
end

Expand Down Expand Up @@ -1506,7 +1498,7 @@ def normalized_site
site_string
end
# All normalized values should be UTF-8
@normalized_site.force_encoding(Encoding::UTF_8) if @normalized_site
force_utf8_encoding_if_needed(@normalized_site)
@normalized_site
end

Expand Down Expand Up @@ -1569,7 +1561,7 @@ def normalized_path
result
end
# All normalized values should be UTF-8
@normalized_path.force_encoding(Encoding::UTF_8) if @normalized_path
force_utf8_encoding_if_needed(@normalized_path)
@normalized_path
end

Expand Down Expand Up @@ -1645,7 +1637,7 @@ def normalized_query(*flags)
component == "" ? nil : component
end
# All normalized values should be UTF-8
@normalized_query.force_encoding(Encoding::UTF_8) if @normalized_query
force_utf8_encoding_if_needed(@normalized_query)
@normalized_query
end

Expand Down Expand Up @@ -1841,9 +1833,7 @@ def normalized_fragment
component == "" ? nil : component
end
# All normalized values should be UTF-8
if @normalized_fragment
@normalized_fragment.force_encoding(Encoding::UTF_8)
end
force_utf8_encoding_if_needed(@normalized_fragment)
@normalized_fragment
end

Expand Down Expand Up @@ -2556,5 +2546,15 @@ def remove_composite_values
remove_instance_variable(:@uri_string) if defined?(@uri_string)
remove_instance_variable(:@hash) if defined?(@hash)
end

##
# Converts the string to be UTF-8 if it is not already UTF-8
#
# @api private
def force_utf8_encoding_if_needed(str)
if str && str.encoding != Encoding::UTF_8
str.force_encoding(Encoding::UTF_8)
end
end
end
end
66 changes: 66 additions & 0 deletions spec/addressable/uri_spec.rb
Expand Up @@ -998,6 +998,72 @@ def to_s
end
end

describe Addressable::URI, "when normalized and then deeply frozen" do
dentarg marked this conversation as resolved.
Show resolved Hide resolved
dentarg marked this conversation as resolved.
Show resolved Hide resolved
sporkmonger marked this conversation as resolved.
Show resolved Hide resolved
sporkmonger marked this conversation as resolved.
Show resolved Hide resolved
sporkmonger marked this conversation as resolved.
Show resolved Hide resolved
sporkmonger marked this conversation as resolved.
Show resolved Hide resolved
before do
@uri = Addressable::URI.parse(
"http://user:password@example.com:8080/path?query=value#fragment"
).normalize!

@uri.instance_variables.each do |var|
@uri.instance_variable_set(var, @uri.instance_variable_get(var).freeze)
end

@uri.freeze
end

it "#normalized_scheme should not error" do
expect { @uri.normalized_scheme }.not_to raise_error
end

it "#normalized_user should not error" do
expect { @uri.normalized_user }.not_to raise_error
end

it "#normalized_password should not error" do
expect { @uri.normalized_password }.not_to raise_error
end

it "#normalized_userinfo should not error" do
expect { @uri.normalized_userinfo }.not_to raise_error
end

it "#normalized_host should not error" do
expect { @uri.normalized_host }.not_to raise_error
end

it "#normalized_authority should not error" do
expect { @uri.normalized_authority }.not_to raise_error
end

it "#normalized_port should not error" do
expect { @uri.normalized_port }.not_to raise_error
end

it "#normalized_site should not error" do
expect { @uri.normalized_site }.not_to raise_error
end

it "#normalized_path should not error" do
expect { @uri.normalized_path }.not_to raise_error
end

it "#normalized_query should not error" do
expect { @uri.normalized_query }.not_to raise_error
end

it "#normalized_fragment should not error" do
expect { @uri.normalized_fragment }.not_to raise_error
end

it "should be frozen" do
expect(@uri).to be_frozen
end

it "should not allow destructive operations" do
expect { @uri.normalize! }.to raise_error(RuntimeError)
end
end

describe Addressable::URI, "when created from string components" do
before do
@uri = Addressable::URI.new(
Expand Down