1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Allow multiline to be passed in routes when using wildcards.

Fixed a bug in action_dispatch where routes with newlines weren't detected when using wildcard segments
This commit is contained in:
ignacio-chiazzo 2021-10-12 20:40:14 -04:00
parent e7fb2b114e
commit 4df32bc139
7 changed files with 64 additions and 15 deletions

View file

@ -53,7 +53,7 @@ module ActionDispatch
if formatted != false if formatted != false
# Add a constraint for wildcard route to make it non-greedy and # Add a constraint for wildcard route to make it non-greedy and
# match the optional format part of the route by default. # match the optional format part of the route by default.
wildcard_options[node.name.to_sym] ||= /.+?/ wildcard_options[node.name.to_sym] ||= /.+?/m
end end
end end

View file

@ -91,7 +91,8 @@ module ActionDispatch
# as requirements. # as requirements.
def requirements def requirements
@defaults.merge(path.requirements).delete_if { |_, v| @defaults.merge(path.requirements).delete_if { |_, v|
/.+?/ == v /.+?/ == v ||
/.+?/m == v
} }
end end

View file

@ -146,7 +146,7 @@ module ActionDispatch
end end
requirements, conditions = split_constraints ast.path_params, constraints requirements, conditions = split_constraints ast.path_params, constraints
verify_regexp_requirements requirements.map(&:last).grep(Regexp) verify_regexp_requirements requirements, ast.wildcard_options
formats = normalize_format(formatted) formats = normalize_format(formatted)
@ -246,14 +246,18 @@ module ActionDispatch
end end
end end
def verify_regexp_requirements(requirements) def verify_regexp_requirements(requirements, wildcard_options)
requirements.each do |requirement| requirements.each do |requirement, regex|
if ANCHOR_CHARACTERS_REGEX.match?(requirement.source) next unless regex.is_a? Regexp
if ANCHOR_CHARACTERS_REGEX.match?(regex.source)
raise ArgumentError, "Regexp anchor characters are not allowed in routing requirements: #{requirement.inspect}" raise ArgumentError, "Regexp anchor characters are not allowed in routing requirements: #{requirement.inspect}"
end end
if requirement.multiline? if regex.multiline?
raise ArgumentError, "Regexp multiline option is not allowed in routing requirements: #{requirement.inspect}" next if wildcard_options.key?(requirement)
raise ArgumentError, "Regexp multiline option is not allowed in routing requirements: #{regex.inspect}"
end end
end end
end end

View file

@ -624,6 +624,34 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
url_for(rs, controller: "content", action: "show_file", path: %w(pages boo)) url_for(rs, controller: "content", action: "show_file", path: %w(pages boo))
end end
def test_escapes_newline_character_for_dynamic_path
rs.draw do
get "/dynamic/:dynamic_segment" => "subpath_books#show", as: :dynamic
ActiveSupport::Deprecation.silence do
get ":controller/:action/:id"
end
end
results = rs.recognize_path("/dynamic/a%0Anewline")
assert(results, "Recognition should have succeeded")
assert_equal("a\nnewline", results[:dynamic_segment])
end
def test_escapes_newline_character_for_wildcard_path
rs.draw do
get "/wildcard/*wildcard_segment" => "subpath_books#show", as: :wildcard
ActiveSupport::Deprecation.silence do
get ":controller/:action/:id"
end
end
results = rs.recognize_path("/wildcard/a%0Anewline")
assert(results, "Recognition should have succeeded")
assert_equal("a\nnewline", results[:wildcard_segment])
end
def test_dynamic_recall_paths_allowed def test_dynamic_recall_paths_allowed
rs.draw do rs.draw do
get "*path" => "content#show_file" get "*path" => "content#show_file"

View file

@ -92,7 +92,7 @@ module ActionDispatch
scope = Mapper::Scope.new({}) scope = Mapper::Scope.new({})
ast = Journey::Parser.parse "/store/:name(*rest)" ast = Journey::Parser.parse "/store/:name(*rest)"
m = Mapper::Mapping.build(scope, FakeSet.new, ast, "foo", "bar", nil, [:get], nil, {}, true, options) m = Mapper::Mapping.build(scope, FakeSet.new, ast, "foo", "bar", nil, [:get], nil, {}, true, options)
assert_equal(/.+?/, m.requirements[:rest]) assert_equal(/.+?/m, m.requirements[:rest])
end end
def test_via_scope def test_via_scope
@ -137,7 +137,7 @@ module ActionDispatch
mapper = Mapper.new fakeset mapper = Mapper.new fakeset
mapper.get "/*path", to: "pages#show" mapper.get "/*path", to: "pages#show"
assert_equal "/*path(.:format)", fakeset.asts.first.to_s assert_equal "/*path(.:format)", fakeset.asts.first.to_s
assert_equal(/.+?/, fakeset.requirements.first[:path]) assert_equal(/.+?/m, fakeset.requirements.first[:path])
end end
def test_map_wildcard_with_other_element def test_map_wildcard_with_other_element
@ -145,7 +145,7 @@ module ActionDispatch
mapper = Mapper.new fakeset mapper = Mapper.new fakeset
mapper.get "/*path/foo/:bar", to: "pages#show" mapper.get "/*path/foo/:bar", to: "pages#show"
assert_equal "/*path/foo/:bar(.:format)", fakeset.asts.first.to_s assert_equal "/*path/foo/:bar(.:format)", fakeset.asts.first.to_s
assert_equal(/.+?/, fakeset.requirements.first[:path]) assert_equal(/.+?/m, fakeset.requirements.first[:path])
end end
def test_map_wildcard_with_multiple_wildcard def test_map_wildcard_with_multiple_wildcard
@ -153,8 +153,8 @@ module ActionDispatch
mapper = Mapper.new fakeset mapper = Mapper.new fakeset
mapper.get "/*foo/*bar", to: "pages#show" mapper.get "/*foo/*bar", to: "pages#show"
assert_equal "/*foo/*bar(.:format)", fakeset.asts.first.to_s assert_equal "/*foo/*bar(.:format)", fakeset.asts.first.to_s
assert_equal(/.+?/, fakeset.requirements.first[:foo]) assert_equal(/.+?/m, fakeset.requirements.first[:foo])
assert_equal(/.+?/, fakeset.requirements.first[:bar]) assert_equal(/.+?/m, fakeset.requirements.first[:bar])
end end
def test_map_wildcard_with_format_false def test_map_wildcard_with_format_false

View file

@ -149,6 +149,22 @@ module ActionDispatch
assert_equal "/users/1.json", url_helpers.user_path(1, :json) assert_equal "/users/1.json", url_helpers.user_path(1, :json)
end end
test "escape new line for dynamic params" do
draw do
get "/dynamic/:dynamic_segment", to: SimpleApp.new("foo#index"), as: :dynamic
end
assert_equal "/dynamic/a%0Anewline", url_helpers.dynamic_path(dynamic_segment: "a\nnewline")
end
test "escape new line for wildcard params" do
draw do
get "/wildcard/*wildcard_segment", to: SimpleApp.new("foo#index"), as: :wildcard
end
assert_equal "/wildcard/a%0Anewline", url_helpers.wildcard_path(wildcard_segment: "a\nnewline")
end
private private
def draw(&block) def draw(&block)
@set.draw(&block) @set.draw(&block)

View file

@ -67,7 +67,7 @@ module ActionDispatch
ast = Ast.new(tree, true) ast = Ast.new(tree, true)
wildcard_options = ast.wildcard_options wildcard_options = ast.wildcard_options
assert_equal %r{.+?}, wildcard_options[:glob] assert_equal %r{.+?}m, wildcard_options[:glob]
end end
def test_wildcard_options_when_false def test_wildcard_options_when_false
@ -83,7 +83,7 @@ module ActionDispatch
ast = Ast.new(tree, nil) ast = Ast.new(tree, nil)
wildcard_options = ast.wildcard_options wildcard_options = ast.wildcard_options
assert_equal %r{.+?}, wildcard_options[:glob] assert_equal %r{.+?}m, wildcard_options[:glob]
end end
end end
end end