From 3891c725ade96b7a847ac133496ad307bd05e920 Mon Sep 17 00:00:00 2001 From: Shugo Maeda Date: Thu, 8 Nov 2018 21:02:45 +0900 Subject: sub, sub!, gsub, and gsub! should set back references --- .../core_ext/string/output_safety.rb | 46 +++++++++++++++++++++- activesupport/test/safe_buffer_test.rb | 18 +++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index 3a80de4617..e3f62d7d26 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -135,10 +135,12 @@ module ActiveSupport #:nodoc: class SafeBuffer < String UNSAFE_STRING_METHODS = %w( capitalize chomp chop delete delete_prefix delete_suffix - downcase gsub lstrip next reverse rstrip slice squeeze strip - sub succ swapcase tr tr_s unicode_normalize upcase + downcase lstrip next reverse rstrip slice squeeze strip + succ swapcase tr tr_s unicode_normalize upcase ) + UNSAFE_STRING_METHODS_WITH_BACKREF = %w(gsub sub) + alias_method :original_concat, :concat private :original_concat @@ -249,11 +251,51 @@ module ActiveSupport #:nodoc: end end + UNSAFE_STRING_METHODS_WITH_BACKREF.each do |unsafe_method| + if unsafe_method.respond_to?(unsafe_method) + class_eval <<-EOT, __FILE__, __LINE__ + 1 + def #{unsafe_method}(*args, &block) + if block + to_str.#{unsafe_method}(*args) { |*params| + set_block_back_references(block, $~) + block.call(*params) + } + else + to_str.#{unsafe_method}(*args) + end + end + + def #{unsafe_method}!(*args, &block) + @html_safe = false + if block + super(*args) { |*params| + set_block_back_references(block, $~) + block.call(*params) + } + else + super + end + end + EOT + end + end + private def html_escape_interpolated_argument(arg) (!html_safe? || arg.html_safe?) ? arg : CGI.escapeHTML(arg.to_s) end + + def set_block_back_references(block, match_data) + Thread.current[:__active_support_safe_buffer_backref] = match_data + begin + block.binding.eval(<<-EOC) + $~ = Thread.current[:__active_support_safe_buffer_backref] + EOC + ensure + Thread.current[:__active_support_safe_buffer_backref] = nil + end + end end end diff --git a/activesupport/test/safe_buffer_test.rb b/activesupport/test/safe_buffer_test.rb index 49a3951623..9449adb6de 100644 --- a/activesupport/test/safe_buffer_test.rb +++ b/activesupport/test/safe_buffer_test.rb @@ -216,4 +216,22 @@ class SafeBufferTest < ActiveSupport::TestCase x = "Hello".html_safe assert_nil x[/a/, 1] end + + test "Should set back references" do + a = "foo123".html_safe + a2 = a.sub(/([a-z]+)([0-9]+)/) { $2 + $1 } + assert_equal "123foo", a2 + assert_not_predicate a2, :html_safe? + a.sub!(/([a-z]+)([0-9]+)/) { $2 + $1 } + assert_equal "123foo", a + assert_not_predicate a, :html_safe? + + b = "foo123 bar456".html_safe + b2 = b.gsub(/([a-z]+)([0-9]+)/) { $2 + $1 } + assert_equal "123foo 456bar", b2 + assert_not_predicate b2, :html_safe? + b.gsub!(/([a-z]+)([0-9]+)/) { $2 + $1 } + assert_equal "123foo 456bar", b + assert_not_predicate b, :html_safe? + end end -- cgit v1.2.3 From 94ac3f782027c4b707470b1aa0f5f66c6702ad9f Mon Sep 17 00:00:00 2001 From: Shugo Maeda Date: Thu, 8 Nov 2018 23:28:40 +0900 Subject: Add a commented code example of what will be produced --- .../core_ext/string/output_safety.rb | 44 +++++++++++----------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index e3f62d7d26..c27d7bbc78 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -254,28 +254,28 @@ module ActiveSupport #:nodoc: UNSAFE_STRING_METHODS_WITH_BACKREF.each do |unsafe_method| if unsafe_method.respond_to?(unsafe_method) class_eval <<-EOT, __FILE__, __LINE__ + 1 - def #{unsafe_method}(*args, &block) - if block - to_str.#{unsafe_method}(*args) { |*params| - set_block_back_references(block, $~) - block.call(*params) - } - else - to_str.#{unsafe_method}(*args) - end - end - - def #{unsafe_method}!(*args, &block) - @html_safe = false - if block - super(*args) { |*params| - set_block_back_references(block, $~) - block.call(*params) - } - else - super - end - end + def #{unsafe_method}(*args, &block) # def gsub(*args, &block) + if block # if block + to_str.#{unsafe_method}(*args) { |*params| # to_str.gsub(*args) { |*params| + set_block_back_references(block, $~) # set_block_back_references(block, $~) + block.call(*params) # block.call(*params) + } # } + else # else + to_str.#{unsafe_method}(*args) # to_str.gsub(*args) + end # end + end # end + + def #{unsafe_method}!(*args, &block) # def gsub!(*args, &block) + @html_safe = false # @html_safe = false + if block # if block + super(*args) { |*params| # super(*args) { |*params| + set_block_back_references(block, $~) # set_block_back_references(block, $~) + block.call(*params) # block.call(*params) + } # } + else # else + super # super + end # end + end # end EOT end end -- cgit v1.2.3 From cd40043357491f386a4e3dd095ed4ad6abb54f81 Mon Sep 17 00:00:00 2001 From: Shugo Maeda Date: Thu, 8 Nov 2018 23:47:10 +0900 Subject: Remove trailing space --- activesupport/lib/active_support/core_ext/string/output_safety.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index c27d7bbc78..55579ec259 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -256,7 +256,7 @@ module ActiveSupport #:nodoc: class_eval <<-EOT, __FILE__, __LINE__ + 1 def #{unsafe_method}(*args, &block) # def gsub(*args, &block) if block # if block - to_str.#{unsafe_method}(*args) { |*params| # to_str.gsub(*args) { |*params| + to_str.#{unsafe_method}(*args) { |*params| # to_str.gsub(*args) { |*params| set_block_back_references(block, $~) # set_block_back_references(block, $~) block.call(*params) # block.call(*params) } # } -- cgit v1.2.3 From e7da1ddd6172fa36a8c0159652111b11745c81da Mon Sep 17 00:00:00 2001 From: Shugo Maeda Date: Thu, 14 Feb 2019 17:32:39 +0900 Subject: Eliminate a thread local variable as suggested by nobu --- .../lib/active_support/core_ext/string/output_safety.rb | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'activesupport') diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb index 55579ec259..1371abbc4a 100644 --- a/activesupport/lib/active_support/core_ext/string/output_safety.rb +++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb @@ -287,14 +287,7 @@ module ActiveSupport #:nodoc: end def set_block_back_references(block, match_data) - Thread.current[:__active_support_safe_buffer_backref] = match_data - begin - block.binding.eval(<<-EOC) - $~ = Thread.current[:__active_support_safe_buffer_backref] - EOC - ensure - Thread.current[:__active_support_safe_buffer_backref] = nil - end + block.binding.eval("proc { |m| $~ = m }").call(match_data) end end end -- cgit v1.2.3