Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

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

Merged
merged 3 commits into from

3 participants

Lauri Hahne Santiago Pastorino Dieter Komendera
Lauri Hahne

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

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

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.

lhahne added some commits
Lauri Hahne lhahne 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 lhahne made sure that the possible new output_buffer created by CacheHelper …
…is of the same type as the original
39a4f67
Lauri Hahne

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

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
Owner

Closed in PR 2219

Santiago Pastorino spastorino closed this
Santiago Pastorino spastorino reopened this
Santiago Pastorino
Owner

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

Dieter Komendera

@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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 15, 2011
  1. Lauri Hahne
Commits on Jul 17, 2011
  1. Lauri Hahne

    Added tests for the output_buffer returned by CacheHelper

    lhahne authored
    The output_buffer returned by CacheHelper should be html_safe if the original buffer is html_safe.
  2. Lauri Hahne

    made sure that the possible new output_buffer created by CacheHelper …

    lhahne authored
    …is of the same type as the original
This page is out of date. Refresh to see the latest.
4 actionpack/lib/action_view/helpers/cache_helper.rb
View
@@ -53,10 +53,10 @@ def fragment_for(name = {}, options = nil, &block) #:nodoc:
# This dance is needed because Builder can't use capture
pos = output_buffer.length
yield
- if output_buffer.is_a?(ActionView::OutputBuffer)
+ if output_buffer.html_safe?
safe_output_buffer = output_buffer.to_str
fragment = safe_output_buffer.slice!(pos..-1)
- self.output_buffer = ActionView::OutputBuffer.new(safe_output_buffer)
+ self.output_buffer = output_buffer.class.new(safe_output_buffer)
else
fragment = output_buffer.slice!(pos..-1)
end
50 actionpack/test/controller/caching_test.rb
View
@@ -785,3 +785,53 @@ def test_xml_formatted_fragment_caching
assert_equal " <p>Builder</p>\n", @store.read('views/test.host/functional_caching/formatted_fragment_cached')
end
end
+
+class CacheHelperOutputBufferTest < ActionController::TestCase
+
+ class MockController
+ def read_fragment(name, options)
+ return false
+ end
+
+ def write_fragment(name, fragment, options)
+ fragment
+ end
+ end
+
+ def setup
+ super
+ end
+
+ def test_output_buffer
+ output_buffer = ActionView::OutputBuffer.new
+ controller = MockController.new
+ cache_helper = Object.new
+ cache_helper.extend(ActionView::Helpers::CacheHelper)
+ cache_helper.expects(:controller).returns(controller).at_least(0)
+ cache_helper.expects(:output_buffer).returns(output_buffer).at_least(0)
+ # if the output_buffer is changed, the new one should be html_safe and of the same type
+ cache_helper.expects(:output_buffer=).with(responds_with(:html_safe?, true)).with(instance_of(output_buffer.class)).at_least(0)
+
+ assert_nothing_raised do
+ cache_helper.send :fragment_for, 'Test fragment name', 'Test fragment', &Proc.new{ nil }
+ assert output_buffer.html_safe?, "Output buffer should stay html_safe"
+ end
+ end
+
+ def test_safe_buffer
+ output_buffer = ActiveSupport::SafeBuffer.new
+ controller = MockController.new
+ cache_helper = Object.new
+ cache_helper.extend(ActionView::Helpers::CacheHelper)
+ cache_helper.expects(:controller).returns(controller).at_least(0)
+ cache_helper.expects(:output_buffer).returns(output_buffer).at_least(0)
+ # if the output_buffer is changed, the new one should be html_safe and of the same type
+ cache_helper.expects(:output_buffer=).with(responds_with(:html_safe?, true)).with(instance_of(output_buffer.class)).at_least(0)
+
+ assert_nothing_raised do
+ cache_helper.send :fragment_for, 'Test fragment name', 'Test fragment', &Proc.new{ nil }
+ assert output_buffer.html_safe?, "Output buffer should stay html_safe"
+ end
+ end
+
+end
Something went wrong with that request. Please try again.