aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJanosch Müller <janosch84@gmail.com>2018-09-28 02:50:21 +0200
committerRafael França <rafaelmfranca@gmail.com>2018-09-27 20:50:21 -0400
commit47f2686148bcaa04f24c1ed895d75ff877be12e9 (patch)
tree888f05b2c6892e83638954201ecb040a910ef1c2
parent6b9cc6fee11df3070eaa7621c004669c64f9f69d (diff)
downloadrails-47f2686148bcaa04f24c1ed895d75ff877be12e9.tar.gz
rails-47f2686148bcaa04f24c1ed895d75ff877be12e9.tar.bz2
rails-47f2686148bcaa04f24c1ed895d75ff877be12e9.zip
Handle more unsafe String methods (#33990)
* Handle more unsafe String methods * Fix codeclimate issue * Revert stylistic change [Janosch Müller + Rafael Mendonça França]
-rw-r--r--activesupport/CHANGELOG.md5
-rw-r--r--activesupport/lib/active_support/core_ext/string/output_safety.rb17
-rw-r--r--activesupport/test/core_ext/string_ext_test.rb48
-rw-r--r--activesupport/test/safe_buffer_test.rb43
4 files changed, 102 insertions, 11 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index 37bd4da15e..39f366bc88 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,3 +1,8 @@
+* Treat `#delete_prefix`, `#delete_suffix` and `#unicode_normalize` results as non-`html_safe`.
+ Ensure safety of arguments for `#insert`, `#[]=` and `#replace` calls on `html_safe` Strings.
+
+ *Janosch Müller*
+
* Changed `ActiveSupport::TaggedLogging.new` to return a new logger instance instead
of mutating the one received as parameter.
diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb
index d837bb10aa..3a80de4617 100644
--- a/activesupport/lib/active_support/core_ext/string/output_safety.rb
+++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb
@@ -134,8 +134,9 @@ end
module ActiveSupport #:nodoc:
class SafeBuffer < String
UNSAFE_STRING_METHODS = %w(
- capitalize chomp chop delete downcase gsub lstrip next reverse rstrip
- slice squeeze strip sub succ swapcase tr tr_s upcase
+ capitalize chomp chop delete delete_prefix delete_suffix
+ downcase gsub lstrip next reverse rstrip slice squeeze strip
+ sub succ swapcase tr tr_s unicode_normalize upcase
)
alias_method :original_concat, :concat
@@ -186,10 +187,22 @@ module ActiveSupport #:nodoc:
end
alias << concat
+ def insert(index, value)
+ super(index, html_escape_interpolated_argument(value))
+ end
+
def prepend(value)
super(html_escape_interpolated_argument(value))
end
+ def replace(value)
+ super(html_escape_interpolated_argument(value))
+ end
+
+ def []=(index, value)
+ super(index, html_escape_interpolated_argument(value))
+ end
+
def +(other)
dup.concat(other)
end
diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb
index 81299e5b58..a26473dc84 100644
--- a/activesupport/test/core_ext/string_ext_test.rb
+++ b/activesupport/test/core_ext/string_ext_test.rb
@@ -892,6 +892,54 @@ class OutputSafetyTest < ActiveSupport::TestCase
assert_predicate string, :html_safe?
end
+ test "Inserting safe into safe yields safe" do
+ string = "foo".html_safe
+ string.insert(0, "<b>".html_safe)
+
+ assert_equal "<b>foo", string
+ assert_predicate string, :html_safe?
+ end
+
+ test "Inserting unsafe into safe yields escaped safe" do
+ string = "foo".html_safe
+ string.insert(0, "<b>")
+
+ assert_equal "&lt;b&gt;foo", string
+ assert_predicate string, :html_safe?
+ end
+
+ test "Replacing safe with safe yields safe" do
+ string = "foo".html_safe
+ string.replace("<b>".html_safe)
+
+ assert_equal "<b>", string
+ assert_predicate string, :html_safe?
+ end
+
+ test "Replacing safe with unsafe yields escaped safe" do
+ string = "foo".html_safe
+ string.replace("<b>")
+
+ assert_equal "&lt;b&gt;", string
+ assert_predicate string, :html_safe?
+ end
+
+ test "Replacing index of safe with safe yields safe" do
+ string = "foo".html_safe
+ string[0] = "<b>".html_safe
+
+ assert_equal "<b>oo", string
+ assert_predicate string, :html_safe?
+ end
+
+ test "Replacing index of safe with unsafe yields escaped safe" do
+ string = "foo".html_safe
+ string[0] = "<b>"
+
+ assert_equal "&lt;b&gt;oo", string
+ assert_predicate string, :html_safe?
+ end
+
test "emits normal string yaml" do
assert_equal "foo".to_yaml, "foo".html_safe.to_yaml(foo: 1)
end
diff --git a/activesupport/test/safe_buffer_test.rb b/activesupport/test/safe_buffer_test.rb
index 70dec6b3d2..49a3951623 100644
--- a/activesupport/test/safe_buffer_test.rb
+++ b/activesupport/test/safe_buffer_test.rb
@@ -75,16 +75,41 @@ class SafeBufferTest < ActiveSupport::TestCase
assert_equal "my_test", str
end
- test "Should not return safe buffer from gsub" do
- altered_buffer = @buffer.gsub("", "asdf")
- assert_equal "asdf", altered_buffer
- assert_not_predicate altered_buffer, :html_safe?
- end
+ {
+ capitalize: nil,
+ chomp: nil,
+ chop: nil,
+ delete: "foo",
+ delete_prefix: "foo",
+ delete_suffix: "foo",
+ downcase: nil,
+ gsub: ["foo", "bar"],
+ lstrip: nil,
+ next: nil,
+ reverse: nil,
+ rstrip: nil,
+ slice: "foo",
+ squeeze: nil,
+ strip: nil,
+ sub: ["foo", "bar"],
+ succ: nil,
+ swapcase: nil,
+ tr: ["foo", "bar"],
+ tr_s: ["foo", "bar"],
+ unicode_normalize: nil,
+ upcase: nil,
+ }.each do |unsafe_method, dummy_args|
+ test "Should not return safe buffer from #{unsafe_method}" do
+ skip unless String.method_defined?(unsafe_method)
+ altered_buffer = @buffer.send(unsafe_method, *dummy_args)
+ assert_not_predicate altered_buffer, :html_safe?
+ end
- test "Should not return safe buffer from gsub!" do
- @buffer.gsub!("", "asdf")
- assert_equal "asdf", @buffer
- assert_not_predicate @buffer, :html_safe?
+ test "Should not return safe buffer from #{unsafe_method}!" do
+ skip unless String.method_defined?("#{unsafe_method}!")
+ @buffer.send("#{unsafe_method}!", *dummy_args)
+ assert_not_predicate @buffer, :html_safe?
+ end
end
test "Should escape dirty buffers on add" do