aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
authorAndrew White <andyw@pixeltrix.co.uk>2012-05-20 16:44:42 +0100
committerAndrew White <andyw@pixeltrix.co.uk>2012-05-20 19:07:04 +0100
commit3fc561a1f71edf1c2bae695cafa03909d24a5ca3 (patch)
treecd99e00314ff93e8b8c28d88677c7bd312ffd9de /actionpack
parent66eb3f02cc0894f08c4f912ba8bf6fb1f87e9a4a (diff)
downloadrails-3fc561a1f71edf1c2bae695cafa03909d24a5ca3.tar.gz
rails-3fc561a1f71edf1c2bae695cafa03909d24a5ca3.tar.bz2
rails-3fc561a1f71edf1c2bae695cafa03909d24a5ca3.zip
Return 400 Bad Request for URL paths with invalid encoding.
Passing path parameters with invalid encoding is likely to trigger errors further on like `ArgumentError (invalid byte sequence in UTF-8)`. This will result in a 500 error whereas the better error to return is a 400 error which allows exception notification libraries to filter it out if they wish. Closes #4450
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/CHANGELOG.md2
-rw-r--r--actionpack/lib/action_dispatch/routing/redirection.rb9
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb9
-rw-r--r--actionpack/test/dispatch/routing_test.rb31
4 files changed, 51 insertions, 0 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 5d4ae16c09..94b3490b80 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,5 +1,7 @@
## Rails 4.0.0 (unreleased) ##
+* URL path parameters with invalid encoding now raise ActionController::BadRequest. *Andrew White*
+
* Malformed query and request parameter hashes now raise ActionController::BadRequest. *Andrew White*
* Add `divider` option to `grouped_options_for_select` to generate a separator
diff --git a/actionpack/lib/action_dispatch/routing/redirection.rb b/actionpack/lib/action_dispatch/routing/redirection.rb
index b3823bb496..205ff44b1c 100644
--- a/actionpack/lib/action_dispatch/routing/redirection.rb
+++ b/actionpack/lib/action_dispatch/routing/redirection.rb
@@ -2,6 +2,7 @@ require 'action_dispatch/http/request'
require 'active_support/core_ext/uri'
require 'active_support/core_ext/array/extract_options'
require 'rack/utils'
+require 'action_controller/metal/exceptions'
module ActionDispatch
module Routing
@@ -16,6 +17,14 @@ module ActionDispatch
def call(env)
req = Request.new(env)
+ # If any of the path parameters has a invalid encoding then
+ # raise since it's likely to trigger errors further on.
+ req.symbolized_path_parameters.each do |key, value|
+ unless value.valid_encoding?
+ raise ActionController::BadRequest, "Invalid parameter: #{key} => #{value}"
+ end
+ end
+
uri = URI.parse(path(req.symbolized_path_parameters, req))
uri.scheme ||= req.scheme
uri.host ||= req.host
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 0ae668d42a..1d0a67d0d2 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -26,6 +26,15 @@ module ActionDispatch
def call(env)
params = env[PARAMETERS_KEY]
+
+ # If any of the path parameters has a invalid encoding then
+ # raise since it's likely to trigger errors further on.
+ params.each do |key, value|
+ unless value.valid_encoding?
+ raise ActionController::BadRequest, "Invalid parameter: #{key} => #{value}"
+ end
+ end
+
prepare_params!(params)
# Just raise undefined constant errors if a controller was specified as default.
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index 1a8f40037f..00d09282ca 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -2697,3 +2697,34 @@ class TestUrlConstraints < ActionDispatch::IntegrationTest
assert_response :success
end
end
+
+class TestInvalidUrls < ActionDispatch::IntegrationTest
+ class FooController < ActionController::Base
+ def show
+ render :text => "foo#show"
+ end
+ end
+
+ test "invalid UTF-8 encoding returns a 400 Bad Request" do
+ with_routing do |set|
+ set.draw do
+ get "/bar/:id", :to => redirect("/foo/show/%{id}")
+ get "/foo/show(/:id)", :to => "test_invalid_urls/foo#show"
+ get "/foo(/:action(/:id))", :to => "test_invalid_urls/foo"
+ get "/:controller(/:action(/:id))"
+ end
+
+ get "/%E2%EF%BF%BD%A6"
+ assert_response :bad_request
+
+ get "/foo/%E2%EF%BF%BD%A6"
+ assert_response :bad_request
+
+ get "/foo/show/%E2%EF%BF%BD%A6"
+ assert_response :bad_request
+
+ get "/bar/%E2%EF%BF%BD%A6"
+ assert_response :bad_request
+ end
+ end
+end \ No newline at end of file