Skip to content
This repository
Browse code

Ensure [] respects the status of the buffer.

  • Loading branch information...
commit 3d86727e8ffa69da8d2db1619f2853ee722b6e8b 1 parent 2d4cdb0
José Valim authored February 29, 2012 tenderlove committed February 29, 2012
44  activesupport/lib/active_support/core_ext/string/output_safety.rb
@@ -86,19 +86,31 @@ def initialize
86 86
       end
87 87
     end
88 88
 
  89
+    def [](*args)
  90
+      return super if args.size < 2
  91
+
  92
+      if html_safe?
  93
+        new_safe_buffer = super
  94
+        new_safe_buffer.instance_eval { @html_safe = true }
  95
+        new_safe_buffer
  96
+      else
  97
+        to_str[*args]
  98
+      end
  99
+    end
  100
+
89 101
     def safe_concat(value)
90  
-      raise SafeConcatError if dirty?
  102
+      raise SafeConcatError unless html_safe?
91 103
       original_concat(value)
92 104
     end
93 105
 
94 106
     def initialize(*)
95  
-      @dirty = false
  107
+      @html_safe = true
96 108
       super
97 109
     end
98 110
 
99 111
     def initialize_copy(other)
100 112
       super
101  
-      @dirty = other.dirty?
  113
+      @html_safe = other.html_safe?
102 114
     end
103 115
 
104 116
     def clone_empty
@@ -108,7 +120,7 @@ def clone_empty
108 120
     end
109 121
 
110 122
     def concat(value)
111  
-      if dirty? || value.html_safe?
  123
+      if !html_safe? || value.html_safe?
112 124
         super(value)
113 125
       else
114 126
         super(ERB::Util.h(value))
@@ -121,7 +133,7 @@ def +(other)
121 133
     end
122 134
 
123 135
     def html_safe?
124  
-      !dirty?
  136
+      defined?(@html_safe) && @html_safe
125 137
     end
126 138
 
127 139
     def to_s
@@ -144,23 +156,17 @@ def to_yaml(*args)
144 156
     for unsafe_method in UNSAFE_STRING_METHODS
145 157
       if 'String'.respond_to?(unsafe_method)
146 158
         class_eval <<-EOT, __FILE__, __LINE__ + 1
147  
-          def #{unsafe_method}(*args)
148  
-            super.to_str
149  
-          end
150  
-
151  
-          def #{unsafe_method}!(*args)
152  
-            @dirty = true
153  
-            super
154  
-          end
  159
+          def #{unsafe_method}(*args, &block)       # def capitalize(*args, &block)
  160
+            to_str.#{unsafe_method}(*args, &block)  #   to_str.capitalize(*args, &block)
  161
+          end                                       # end
  162
+
  163
+          def #{unsafe_method}!(*args)              # def capitalize!(*args)
  164
+            @html_safe = false                      #   @html_safe = false
  165
+            super                                   #   super
  166
+          end                                       # end
155 167
         EOT
156 168
       end
157 169
     end
158  
-
159  
-    protected
160  
-
161  
-    def dirty?
162  
-      @dirty
163  
-    end
164 170
   end
165 171
 end
166 172
 
36  activesupport/test/safe_buffer_test.rb
@@ -85,24 +85,35 @@ def setup
85 85
     assert_equal "hello&lt;&gt;", clean + @buffer
86 86
   end
87 87
 
88  
-  test "Should concat as a normal string when dirty" do
  88
+  test "Should concat as a normal string when safe" do
89 89
     clean = "hello".html_safe
90 90
     @buffer.gsub!('', '<>')
91 91
     assert_equal "<>hello", @buffer + clean
92 92
   end
93 93
 
94  
-  test "Should preserve dirty? status on copy" do
  94
+  test "Should preserve html_safe? status on copy" do
95 95
     @buffer.gsub!('', '<>')
96 96
     assert !@buffer.dup.html_safe?
97 97
   end
98 98
 
99  
-  test "Should raise an error when safe_concat is called on dirty buffers" do
  99
+  test "Should return safe buffer when added with another safe buffer" do
  100
+    clean = "<script>".html_safe
  101
+    result_buffer = @buffer + clean
  102
+    assert result_buffer.html_safe?
  103
+    assert_equal "<script>", result_buffer
  104
+  end
  105
+
  106
+  test "Should raise an error when safe_concat is called on unsafe buffers" do
100 107
     @buffer.gsub!('', '<>')
101 108
     assert_raise ActiveSupport::SafeBuffer::SafeConcatError do
102 109
       @buffer.safe_concat "BUSTED"
103 110
     end
104 111
   end
105 112
 
  113
+  test "Should not fail if the returned object is not a string" do
  114
+    assert_kind_of NilClass, @buffer.slice("chipchop")
  115
+  end
  116
+
106 117
   test "clone_empty returns an empty buffer" do
107 118
     assert_equal '', ActiveSupport::SafeBuffer.new('foo').clone_empty
108 119
   end
@@ -111,4 +122,23 @@ def setup
111 122
     assert @buffer.clone_empty.html_safe?
112 123
     assert !@buffer.gsub!('', '').clone_empty.html_safe?
113 124
   end
  125
+
  126
+  test "Should be safe when sliced if original value was safe" do
  127
+    new_buffer = @buffer[0,0]
  128
+    assert_not_nil new_buffer
  129
+    assert new_buffer.html_safe?, "should be safe"
  130
+  end
  131
+
  132
+  test "Should continue unsafe on slice" do
  133
+    x = 'foo'.html_safe.gsub!('f', '<script>alert("lolpwnd");</script>')
  134
+
  135
+    # calling gsub! makes the dirty flag true
  136
+    assert !x.html_safe?, "should not be safe"
  137
+
  138
+    # getting a slice of it
  139
+    y = x[0..-1]
  140
+
  141
+    # should still be unsafe
  142
+    assert !y.html_safe?, "should not be safe"
  143
+  end
114 144
 end

0 notes on commit 3d86727

Please sign in to comment.
Something went wrong with that request. Please try again.