diff --git a/ext/erb/escape/escape.c b/ext/erb/escape/escape.c index 903e832..e905bb5 100644 --- a/ext/erb/escape/escape.c +++ b/ext/erb/escape/escape.c @@ -100,10 +100,7 @@ find_next_match_sse2(search_state *search) int next_match_offset = trailing_zeros(search->matches_bitmap); search->matches_bitmap >>= (next_match_offset + 1); search->cstr += next_match_offset; - if (search->cstr > search->end) { - search->cstr = search->end; - return false; - } + RUBY_ASSERT(search->cstr <= search->end); return true; } @@ -170,12 +167,16 @@ static inline uint32_t trailing_zeros64(uint64_t input) static inline bool find_next_match_neon(search_state *search) { - size_t next_match_offset = trailing_zeros64(search->matches_bitmap) / 4; - search->matches_bitmap >>= (next_match_offset + 1) * 4; - search->cstr += next_match_offset; - if (search->cstr > search->end) { - search->cstr = search->end; - return false; + uint32_t trailing_zeros = trailing_zeros64(search->matches_bitmap); + + // uint64_t >>= 64 is undefined behaviour + if (trailing_zeros >= 63) { + search->matches_bitmap = 0; + search->cstr += 15; + } + else { + search->matches_bitmap >>= (trailing_zeros + 1); + search->cstr += trailing_zeros / 4; } return true; } @@ -207,10 +208,10 @@ find_next_neon(search_state *search) const uint8x16_t matches = vorrq_u8(mask2, mask3); const uint8x8_t res = vshrn_n_u16(vreinterpretq_u16_u8(matches), 4); - const uint64_t bitmap = vget_lane_u64(vreinterpret_u64_u8(res), 0) & 0x8888888888888888ull; + const uint64_t bitmap = vget_lane_u64(vreinterpret_u64_u8(res), 0); if (bitmap) { - search->matches_bitmap = bitmap; + search->matches_bitmap = bitmap & 0x8888888888888888ull; return find_next_match_neon(search); } search->cstr += sizeof(uint8x16_t); diff --git a/test/erb/test_erb.rb b/test/erb/test_erb.rb index c789e07..b96c0cb 100644 --- a/test/erb/test_erb.rb +++ b/test/erb/test_erb.rb @@ -43,34 +43,6 @@ def test_with_location assert_match(/\Atest filename:201\b/, e.backtrace[0]) end - def test_html_escape - assert_equal(" !"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", - ERB::Util.html_escape(" !\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~")) - - assert_equal("", ERB::Util.html_escape("")) - assert_equal("abc", ERB::Util.html_escape("abc")) - assert_equal("<<", ERB::Util.html_escape("<\<")) - assert_equal("'&"><" * 10, ERB::Util.html_escape("'&\"><" * 10)) - - assert_equal("", ERB::Util.html_escape(nil)) - assert_equal("123", ERB::Util.html_escape(123)) - - assert_equal(65536+5, ERB::Util.html_escape("x"*65536 + "&").size) - assert_equal(65536+5, ERB::Util.html_escape("&" + "x"*65536).size) - end - - def test_html_escape_to_s - object = Object.new - def object.to_s - "object" - end - assert_equal("object", ERB::Util.html_escape(object)) - end - - def test_html_escape_extension - assert_nil(ERB::Util.method(:html_escape).source_location) - end if RUBY_ENGINE == 'ruby' - def test_concurrent_default_binding # This test randomly fails with JRuby -- NameError: undefined local variable or method `template2' pend if RUBY_ENGINE == 'jruby' @@ -770,13 +742,4 @@ def test_frozen_erb_instance_reused_across_ractors assert_equal(["2", "2"], rs.map(&:value)) RUBY end - - def test_util_html_escape_in_ractor - assert_ractor(<<~RUBY, require: 'erb') - r = Ractor.new do - ERB::Util.html_escape("