Skip to content

Commit 8ccaa34

Browse files
josevalimtenderlove
authored andcommitted
Ensure [] respects the status of the buffer.
1 parent 71d8c77 commit 8ccaa34

File tree

2 files changed

+41
-16
lines changed

2 files changed

+41
-16
lines changed

activesupport/lib/active_support/core_ext/string/output_safety.rb

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -103,19 +103,31 @@ def initialize
103103
end
104104
end
105105

106+
def [](*args)
107+
return super if args.size < 2
108+
109+
if html_safe?
110+
new_safe_buffer = super
111+
new_safe_buffer.instance_eval { @html_safe = true }
112+
new_safe_buffer
113+
else
114+
to_str[*args]
115+
end
116+
end
117+
106118
def safe_concat(value)
107-
raise SafeConcatError if dirty?
119+
raise SafeConcatError unless html_safe?
108120
original_concat(value)
109121
end
110122

111123
def initialize(*)
112-
@dirty = false
124+
@html_safe = true
113125
super
114126
end
115127

116128
def initialize_copy(other)
117129
super
118-
@dirty = other.dirty?
130+
@html_safe = other.html_safe?
119131
end
120132

121133
def clone_empty
@@ -125,7 +137,7 @@ def clone_empty
125137
end
126138

127139
def concat(value)
128-
if dirty? || value.html_safe?
140+
if !html_safe? || value.html_safe?
129141
super(value)
130142
else
131143
super(ERB::Util.h(value))
@@ -138,7 +150,7 @@ def +(other)
138150
end
139151

140152
def html_safe?
141-
!dirty?
153+
defined?(@html_safe) && @html_safe
142154
end
143155

144156
def to_s
@@ -161,18 +173,12 @@ def #{unsafe_method}(*args, &block) # def capitalize(*args, &block)
161173
end # end
162174
163175
def #{unsafe_method}!(*args) # def capitalize!(*args)
164-
@dirty = true # @dirty = true
176+
@html_safe = false # @html_safe = false
165177
super # super
166178
end # end
167179
EOT
168180
end
169181
end
170-
171-
protected
172-
173-
def dirty?
174-
@dirty
175-
end
176182
end
177183
end
178184

activesupport/test/safe_buffer_test.rb

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,13 @@ def test_titleize
8484
assert_equal "hello&lt;&gt;", clean + @buffer
8585
end
8686

87-
test "Should concat as a normal string when dirty" do
87+
test "Should concat as a normal string when safe" do
8888
clean = "hello".html_safe
8989
@buffer.gsub!('', '<>')
9090
assert_equal "<>hello", @buffer + clean
9191
end
9292

93-
test "Should preserve dirty? status on copy" do
93+
test "Should preserve html_safe? status on copy" do
9494
@buffer.gsub!('', '<>')
9595
assert !@buffer.dup.html_safe?
9696
end
@@ -102,14 +102,14 @@ def test_titleize
102102
assert_equal "<script>", result_buffer
103103
end
104104

105-
test "Should raise an error when safe_concat is called on dirty buffers" do
105+
test "Should raise an error when safe_concat is called on unsafe buffers" do
106106
@buffer.gsub!('', '<>')
107107
assert_raise ActiveSupport::SafeBuffer::SafeConcatError do
108108
@buffer.safe_concat "BUSTED"
109109
end
110110
end
111111

112-
test "should not fail if the returned object is not a string" do
112+
test "Should not fail if the returned object is not a string" do
113113
assert_kind_of NilClass, @buffer.slice("chipchop")
114114
end
115115

@@ -121,4 +121,23 @@ def test_titleize
121121
assert @buffer.clone_empty.html_safe?
122122
assert !@buffer.gsub!('', '').clone_empty.html_safe?
123123
end
124+
125+
test "Should be safe when sliced if original value was safe" do
126+
new_buffer = @buffer[0,0]
127+
assert_not_nil new_buffer
128+
assert new_buffer.html_safe?, "should be safe"
129+
end
130+
131+
test "Should continue unsafe on slice" do
132+
x = 'foo'.html_safe.gsub!('f', '<script>alert("lolpwnd");</script>')
133+
134+
# calling gsub! makes the dirty flag true
135+
assert !x.html_safe?, "should not be safe"
136+
137+
# getting a slice of it
138+
y = x[0..-1]
139+
140+
# should still be unsafe
141+
assert !y.html_safe?, "should not be safe"
142+
end
124143
end

0 commit comments

Comments
 (0)