Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ActiveSupport::SafeBuffer#prepend inconsistency #14529

Merged
merged 2 commits into from Apr 2, 2014
Merged

Conversation

rwz
Copy link
Contributor

@rwz rwz commented Mar 30, 2014

Native ruby String#prepend modifies instance in-place, while ActiveSupport::SafeBuffer returns modified version, but the initial object remains unchanged.

a = "bar"           # => "bar"
a.prepend "foo"     # => "foobar"
a                   # => "foobar"
b = "bar".html_safe # => "bar"
b.class             # => ActiveSupport::SafeBuffer
b.prepend "foo"     # => "foobar"
b                   # => "bar", expected "foobar"

assert_equal @string, "otherhello"
end

test "Prepending unsafe unto safe yields escaped safe" do

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unto should be onto?

Copy link
Contributor Author

@rwz rwz Mar 30, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ming-kernel Yep, you're right. Thanks!

test "Prepending unsafe onto safe yields escaped safe" do
other = "other".html_safe
other.prepend "<foo>"
assert other.html_safe?
Copy link
Member

@rafaelfranca rafaelfranca Mar 30, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think prepend should even mark an string html safe. We are changing the behavior and also we may opening a XSS vector.

Copy link
Contributor Author

@rwz rwz Mar 30, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rafaelfranca this is how #concat currently works. I guess it'd make sense to use the same behavior for #prepend

@rwz
Copy link
Contributor Author

rwz commented Apr 1, 2014

What's the status of this? Are we waiting for someone to make a decision or an alternative implementation to show up?

@rafaelfranca
Copy link
Member

rafaelfranca commented Apr 1, 2014

Sorry, many issues to handle. It is missing CHANGELOG

@rwz
Copy link
Contributor Author

rwz commented Apr 1, 2014

Ah, alright, will add changelog then.

@rwz
Copy link
Contributor Author

rwz commented Apr 1, 2014

Done.

@rafaelfranca
Copy link
Member

rafaelfranca commented Apr 1, 2014

We should not remove prepend! without a deprecation message. Mind to add it?

@rwz
Copy link
Contributor Author

rwz commented Apr 1, 2014

ok

Make `#prepend` method modify instance in-place and return self
instead of just returning modified value. That is exactly what
`#prepend!` method was doing previously, so it's deprecated from
now on.
@rwz
Copy link
Contributor Author

rwz commented Apr 1, 2014

Done.

@rafaelfranca
Copy link
Member

rafaelfranca commented Apr 1, 2014

Thank you. I'll merge it

@matthewd
Copy link
Member

matthewd commented Apr 1, 2014

Do we want #concat to be defined via define_method? What about extracting the commonality via a helper...

def concat(value)
  super(maybe_escape(value))
end

def prepend(value)
  super(maybe_escape(value))
end

private
def maybe_escape(value)
  if html_safe? && !value.html_safe?
    ERB::Util.h(value)
  else
    value
  end
end

wdyt?

@rwz
Copy link
Contributor Author

rwz commented Apr 1, 2014

@matthewd that'll produce two separate methods with exact same implementation, which might be even more confusing than a define_method approach. Also, I was reluctant to introduce another helper method on a global class just for that.

@matthewd
Copy link
Member

matthewd commented Apr 1, 2014

Hmm, I just realised there's actually already html_escape_interpolated_argument.

As for visually matching methods, I personally don't think that's particularly confusing -- especially when the very first word of the method body is 'super'... but I'm just thinking out loud. It's up to @rafaelfranca which he prefers. And the one that someone cared enough to make, sure has a certain argument over my bikeshedding. 💙

@rwz
Copy link
Contributor Author

rwz commented Apr 2, 2014

I've added a commit to make use of this helper effectively DRYing the code. Thanks, good catch.

rafaelfranca added a commit that referenced this pull request Apr 2, 2014
ActiveSupport::SafeBuffer#prepend inconsistency
@rafaelfranca rafaelfranca merged commit 8482895 into rails:master Apr 2, 2014
@@ -4,6 +4,7 @@
require 'inflector_test_cases'
require 'constantize_test_cases'

require 'active_support/deprecation/reporting'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the require be on the actual file rather than the test?

Copy link
Member

@rafaelfranca rafaelfranca Apr 2, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍. Fixing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants