From 5621d794a2fa9293d1da489d6b0ee0e7c73c9128 Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Sat, 17 Feb 2024 17:30:34 +1100 Subject: [PATCH] Disable callcc when ASAN is enabled callcc's implementation is fundamentally incompatible with ASAN. Since callcc is deprecated and almost never used, it's probably OK to disable callcc when ruby is compiled with ASAN. [Bug #20273] --- cont.c | 7 +++++++ test/ruby/test_array.rb | 1 + test/ruby/test_beginendblock.rb | 3 +++ test/ruby/test_continuation.rb | 4 ++++ test/ruby/test_enum.rb | 2 ++ test/ruby/test_fiber.rb | 14 ++++++++------ test/ruby/test_hash.rb | 8 ++++++++ test/ruby/test_marshal.rb | 2 ++ test/ruby/test_settracefunc.rb | 21 ++++++++++++--------- 9 files changed, 47 insertions(+), 15 deletions(-) diff --git a/cont.c b/cont.c index cccca9d884faab..5a805cc1ac846a 100644 --- a/cont.c +++ b/cont.c @@ -1775,6 +1775,13 @@ rb_callcc(VALUE self) return rb_yield(val); } } +#ifdef RUBY_ASAN_ENABLED +/* callcc can't possibly work with ASAN; see bug #20273. Also this function + * definition below avoids a "defined and not used" warning. */ +MAYBE_UNUSED(static void notusing_callcc(void)) { rb_callcc(Qnil); } +# define rb_callcc rb_f_notimplement +#endif + static VALUE make_passing_arg(int argc, const VALUE *argv) diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb index e40651eb8e5f81..6e84bdbd02dc25 100644 --- a/test/ruby/test_array.rb +++ b/test/ruby/test_array.rb @@ -3561,6 +3561,7 @@ def need_continuation unless respond_to?(:callcc, true) EnvUtil.suppress_warning {require 'continuation'} end + omit 'requires callcc support' unless respond_to?(:callcc, true) end end diff --git a/test/ruby/test_beginendblock.rb b/test/ruby/test_beginendblock.rb index 3ee1f97e58a60f..3706efab52dd0b 100644 --- a/test/ruby/test_beginendblock.rb +++ b/test/ruby/test_beginendblock.rb @@ -1,5 +1,6 @@ # frozen_string_literal: false require 'test/unit' +EnvUtil.suppress_warning {require 'continuation'} class TestBeginEndBlock < Test::Unit::TestCase DIR = File.dirname(File.expand_path(__FILE__)) @@ -131,6 +132,8 @@ def test_rescue_at_exit end def test_callcc_at_exit + omit 'requires callcc support' unless respond_to?(:callcc) + bug9110 = '[ruby-core:58329][Bug #9110]' assert_ruby_status([], "#{<<~"begin;"}\n#{<<~'end;'}", bug9110) begin; diff --git a/test/ruby/test_continuation.rb b/test/ruby/test_continuation.rb index 8c62d208402f1e..612dbf28c90eee 100644 --- a/test/ruby/test_continuation.rb +++ b/test/ruby/test_continuation.rb @@ -4,6 +4,10 @@ require 'fiber' class TestContinuation < Test::Unit::TestCase + def setup + omit 'requires callcc support' unless respond_to?(:callcc) + end + def test_create assert_equal(:ok, callcc{:ok}) assert_equal(:ok, callcc{|c| c.call :ok}) diff --git a/test/ruby/test_enum.rb b/test/ruby/test_enum.rb index f7c8f012d8c75b..7503e062726d8e 100644 --- a/test/ruby/test_enum.rb +++ b/test/ruby/test_enum.rb @@ -843,6 +843,8 @@ def test_cycle end def test_callcc + omit 'requires callcc support' unless respond_to?(:callcc) + assert_raise(RuntimeError) do c = nil @obj.sort_by {|x| callcc {|c2| c ||= c2 }; x } diff --git a/test/ruby/test_fiber.rb b/test/ruby/test_fiber.rb index cb6e846bc69df6..1fb6103d8a18ba 100644 --- a/test/ruby/test_fiber.rb +++ b/test/ruby/test_fiber.rb @@ -82,12 +82,14 @@ def test_error f.resume f.resume } - assert_raise(RuntimeError){ - Fiber.new{ - @c = callcc{|c| @c = c} - }.resume - @c.call # cross fiber callcc - } + if respond_to?(:callcc) + assert_raise(RuntimeError){ + Fiber.new{ + @c = callcc{|c| @c = c} + }.resume + @c.call # cross fiber callcc + } + end assert_raise(RuntimeError){ Fiber.new{ raise diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb index c72b256bab39aa..ba0def09888955 100644 --- a/test/ruby/test_hash.rb +++ b/test/ruby/test_hash.rb @@ -1359,6 +1359,8 @@ def test_flatten_arity end def test_callcc + omit 'requires callcc support' unless respond_to?(:callcc) + h = @cls[1=>2] c = nil f = false @@ -1379,6 +1381,8 @@ def test_callcc end def test_callcc_iter_level + omit 'requires callcc support' unless respond_to?(:callcc) + bug9105 = '[ruby-dev:47803] [Bug #9105]' h = @cls[1=>2, 3=>4] c = nil @@ -1397,6 +1401,8 @@ def test_callcc_iter_level end def test_callcc_escape + omit 'requires callcc support' unless respond_to?(:callcc) + bug9105 = '[ruby-dev:47803] [Bug #9105]' assert_nothing_raised(RuntimeError, bug9105) do h=@cls[] @@ -1411,6 +1417,8 @@ def test_callcc_escape end def test_callcc_reenter + omit 'requires callcc support' unless respond_to?(:callcc) + bug9105 = '[ruby-dev:47803] [Bug #9105]' assert_nothing_raised(RuntimeError, bug9105) do h = @cls[1=>2,3=>4] diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb index 13645e3aa805f8..79d95777372e12 100644 --- a/test/ruby/test_marshal.rb +++ b/test/ruby/test_marshal.rb @@ -609,6 +609,8 @@ def marshal_load(v) def test_continuation EnvUtil.suppress_warning {require "continuation"} + omit 'requires callcc support' unless respond_to?(:callcc) + c = Bug9523.new assert_raise_with_message(RuntimeError, /Marshal\.dump reentered at marshal_dump/) do Marshal.dump(c) diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb index f7120922c42596..1251f8879f585c 100644 --- a/test/ruby/test_settracefunc.rb +++ b/test/ruby/test_settracefunc.rb @@ -1,5 +1,6 @@ # frozen_string_literal: false require 'test/unit' +EnvUtil.suppress_warning {require 'continuation'} class TestSetTraceFunc < Test::Unit::TestCase def setup @@ -1258,15 +1259,17 @@ def each end } assert_normal_exit src % %q{obj.zip({}) {}}, bug7774 - assert_normal_exit src % %q{ - require 'continuation' - begin - c = nil - obj.sort_by {|x| callcc {|c2| c ||= c2 }; x } - c.call - rescue RuntimeError - end - }, bug7774 + if respond_to?(:callcc) + assert_normal_exit src % %q{ + require 'continuation' + begin + c = nil + obj.sort_by {|x| callcc {|c2| c ||= c2 }; x } + c.call + rescue RuntimeError + end + }, bug7774 + end # TracePoint tp_b = nil