Index: t/unit_core_uri_for.t
===================================================================
--- t/unit_core_uri_for.t	(revision 10686)
+++ t/unit_core_uri_for.t	(working copy)
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 15;
+use Test::More tests => 16;
 use URI;
 
 use_ok('Catalyst');
@@ -103,3 +103,13 @@
     is( $warnings, 0, "no warnings emitted" );
 }
 
+# make sure caller's query parameter hash isn't messed up
+{
+    my $query_params_base = {test => "one two",
+                             bar  => ["foo baz", "bar"]};
+    my $query_params_test = {test => "one two",
+                             bar  => ["foo baz", "bar"]};
+    Catalyst::uri_for($context, '/bar/baz', $query_params_test);
+    is_deeply($query_params_base, $query_params_test,
+              "uri_for() doesn't mess up query parameter hash in the caller");
+}
Index: lib/Catalyst.pm
===================================================================
--- lib/Catalyst.pm	(revision 10686)
+++ lib/Catalyst.pm	(working copy)
@@ -1118,6 +1118,20 @@
     my $params =
       ( scalar @args && ref $args[$#args] eq 'HASH' ? pop @args : {} );
 
+    # make a copy of the parameters hash to prevent the caller's query param
+    # hash from getting munged.  we only really care about copying the array
+    # ref param values since that is the only case where the caller's data
+    # can be modified.
+    my %params_copy;
+    while (my ($key, $val) = each %$params) {
+        if (ref $val eq 'ARRAY') {
+            my @array_copy = @$val;
+            $params_copy{$key} = \@array_copy;
+        } else {
+            $params_copy{$key} = $val;
+        }
+    }
+
     carp "uri_for called with undef argument" if grep { ! defined $_ } @args;
     s/([^$URI::uric])/$URI::Escape::escapes{$1}/go for @args;
 
@@ -1141,10 +1155,10 @@
 
     my $query = '';
 
-    if (my @keys = keys %$params) {
+    if (my @keys = keys %params_copy) {
       # somewhat lifted from URI::_query's query_form
       $query = '?'.join('&', map {
-          my $val = $params->{$_};
+          my $val = $params_copy{$_};
           s/([;\/?:@&=+,\$\[\]%])/$URI::Escape::escapes{$1}/go;
           s/ /+/g;
           my $key = $_;
