Skip to content
This repository

Fix improper detection and handling of html_safe buffer in CacheHelper #2080

Merged
merged 3 commits into from over 2 years ago

3 participants

Lauri Hahne Santiago Pastorino Dieter Komendera
Lauri Hahne
lhahne commented July 14, 2011

This fixes the latest incarnation of #1537 where CacheHelper might try to use splice! for a html_safe buffer which converts the buffer unsafe. This change has been tested against Rails's tests and slim-lang which originally raised this issue.

Santiago Pastorino
Owner

We need a test case in order to merge this.

Lauri Hahne
lhahne commented July 15, 2011

I think test_fragment_caching in caching_tests.rb already tests the bahavior of this function. In addition, even larger changes to this function, such as 114b5e4, have been accepted without specific tests. Anyways, I'll see if I can write a test case over the weekend.

Santiago Pastorino
Owner

@lhahne the commit you're pointing fixes some previously committed failing tests.

Lauri Hahne
lhahne commented July 15, 2011

Ok. I know a way to break the old code so I can write some tests once I discover how to change the buffer in tests.

added some commits July 17, 2011
Lauri Hahne Added tests for the output_buffer returned by CacheHelper
The output_buffer returned by CacheHelper should be html_safe if the original buffer is html_safe.
bc5ccd0
Lauri Hahne made sure that the possible new output_buffer created by CacheHelper …
…is of the same type as the original
39a4f67
Lauri Hahne
lhahne commented July 17, 2011

Ok. I added two tests one of which fails against the current 3-0-stable. After my fix, both tests pass. In addition, I modified CacheBuffer so that any possible new output_buffer is of the original type and made the tests reflect this.

Dieter Komendera
kommen commented July 19, 2011

This seems to be related to #2150

Dieter Komendera

@lhahne: As the output_buffer variable in this line is still pointing to the OutputBuffer created at the beginning of the test, you're explicitly testing here that the old output_buffer is still html_safe. Is this intended? It makes little sense to me, as it is replaced anyway.

Acutally, that depends. If you run this test against the current 3-0-stable with an html_safe output buffer which isn't ActionView::OutputBuffer (that's actually the second test), the execution will reach the else part of the if in fragment_for which causes the buffer to stay the same but converts it to unsafe when splice! is called.

You're right. This is true for 3-0-stable. However, since 03d01ec, which is in 3-1-stable, we don't test for ActionView::OutputBuffer explicitly any more, just for html_safe?. So I guess these asserts can stay for 3-0-stable, we don't need them in 3-1-stable (and master)?

If you are going to remove this, then I think you could also remove the assert_nothing_raised because there isn't much raising happening anymore.

Santiago Pastorino spastorino closed this July 23, 2011
Santiago Pastorino
Owner

Closed in PR 2219

Santiago Pastorino spastorino reopened this July 23, 2011
Santiago Pastorino
Owner

We need to backport PR 2219 to 3-0-stable

Dieter Komendera
kommen commented July 23, 2011

@spastorino in #2219 the regression fixed there is introduced by 03d01ec, which is not in 3-0-stable. So merging this pull request will suffice (assuming we're not backporting 03d01ec to 3-0-stable as well).

Though I think we should update the cache helper test to match the test from master.

Santiago Pastorino spastorino merged commit eead13f into from July 23, 2011
Santiago Pastorino spastorino closed this July 23, 2011
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 3 unique commits by 1 author.

Jul 15, 2011
Lauri Hahne fixed CacheHelper to properly support html_safe output buffers c476a6b
Jul 17, 2011
Lauri Hahne Added tests for the output_buffer returned by CacheHelper
The output_buffer returned by CacheHelper should be html_safe if the original buffer is html_safe.
bc5ccd0
Lauri Hahne made sure that the possible new output_buffer created by CacheHelper …
…is of the same type as the original
39a4f67
This page is out of date. Refresh to see the latest.
4  actionpack/lib/action_view/helpers/cache_helper.rb
@@ -53,10 +53,10 @@ def fragment_for(name = {}, options = nil, &block) #:nodoc:
53 53
           # This dance is needed because Builder can't use capture
54 54
           pos = output_buffer.length
55 55
           yield
56  
-          if output_buffer.is_a?(ActionView::OutputBuffer)
  56
+          if output_buffer.html_safe?
57 57
             safe_output_buffer = output_buffer.to_str
58 58
             fragment = safe_output_buffer.slice!(pos..-1)
59  
-            self.output_buffer = ActionView::OutputBuffer.new(safe_output_buffer)
  59
+            self.output_buffer = output_buffer.class.new(safe_output_buffer)
60 60
           else
61 61
             fragment = output_buffer.slice!(pos..-1)
62 62
           end
50  actionpack/test/controller/caching_test.rb
@@ -785,3 +785,53 @@ def test_xml_formatted_fragment_caching
785 785
     assert_equal "  <p>Builder</p>\n", @store.read('views/test.host/functional_caching/formatted_fragment_cached')
786 786
   end
787 787
 end
  788
+
  789
+class CacheHelperOutputBufferTest < ActionController::TestCase
  790
+
  791
+  class MockController
  792
+    def read_fragment(name, options)
  793
+      return false
  794
+    end
  795
+
  796
+    def write_fragment(name, fragment, options)
  797
+      fragment
  798
+    end
  799
+  end
  800
+
  801
+  def setup
  802
+    super
  803
+  end
  804
+
  805
+  def test_output_buffer
  806
+    output_buffer = ActionView::OutputBuffer.new
  807
+    controller = MockController.new
  808
+    cache_helper = Object.new
  809
+    cache_helper.extend(ActionView::Helpers::CacheHelper)
  810
+    cache_helper.expects(:controller).returns(controller).at_least(0)
  811
+    cache_helper.expects(:output_buffer).returns(output_buffer).at_least(0)
  812
+    # if the output_buffer is changed, the new one should be html_safe and of the same type
  813
+    cache_helper.expects(:output_buffer=).with(responds_with(:html_safe?, true)).with(instance_of(output_buffer.class)).at_least(0)
  814
+
  815
+    assert_nothing_raised do
  816
+      cache_helper.send :fragment_for, 'Test fragment name', 'Test fragment', &Proc.new{ nil }
  817
+      assert output_buffer.html_safe?, "Output buffer should stay html_safe"
  818
+    end
  819
+  end
  820
+
  821
+  def test_safe_buffer
  822
+    output_buffer = ActiveSupport::SafeBuffer.new
  823
+    controller = MockController.new
  824
+    cache_helper = Object.new
  825
+    cache_helper.extend(ActionView::Helpers::CacheHelper)
  826
+    cache_helper.expects(:controller).returns(controller).at_least(0)
  827
+    cache_helper.expects(:output_buffer).returns(output_buffer).at_least(0)
  828
+    # if the output_buffer is changed, the new one should be html_safe and of the same type
  829
+    cache_helper.expects(:output_buffer=).with(responds_with(:html_safe?, true)).with(instance_of(output_buffer.class)).at_least(0)
  830
+
  831
+    assert_nothing_raised do
  832
+      cache_helper.send :fragment_for, 'Test fragment name', 'Test fragment', &Proc.new{ nil }
  833
+      assert output_buffer.html_safe?, "Output buffer should stay html_safe"
  834
+    end
  835
+  end
  836
+
  837
+end
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.