diff options
author | Nobuyoshi Nakada <[email protected]> | 2023-08-11 00:29:32 +0900 |
---|---|---|
committer | Nobuyoshi Nakada <[email protected]> | 2023-08-11 01:56:50 +0900 |
commit | cc0fca2729368f5d5628829a329eb05a86728ace (patch) | |
tree | b004d2d88341b6fa99be88996e58d3e1955dd71d | |
parent | 92cf14b4c5ba4d18140be870bbc5530d1d9e7140 (diff) |
Fix range of `--backtrace-limit`
Also an option command line should have precedence over `RUBYOPT`.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/8200
-rw-r--r-- | internal/cmdlineopt.h | 2 | ||||
-rw-r--r-- | ruby.c | 20 | ||||
-rw-r--r-- | test/ruby/test_rubyoptions.rb | 5 |
3 files changed, 18 insertions, 9 deletions
diff --git a/internal/cmdlineopt.h b/internal/cmdlineopt.h index b2e38bbb47..3b678b1edd 100644 --- a/internal/cmdlineopt.h +++ b/internal/cmdlineopt.h @@ -23,7 +23,7 @@ typedef struct ruby_cmdline_options { ruby_features_t features; ruby_features_t warn; unsigned int dump; - int backtrace_length_limit; + long backtrace_length_limit; #if USE_RJIT struct rb_rjit_options rjit; #endif @@ -203,6 +203,10 @@ enum { ) }; +#define BACKTRACE_LENGTH_LIMIT_VALID_P(n) ((n) >= -1) +#define OPT_BACKTRACE_LENGTH_LIMIT_VALID_P(opt) \ + BACKTRACE_LENGTH_LIMIT_VALID_P((opt)->backtrace_length_limit) + static ruby_cmdline_options_t * cmdline_options_init(ruby_cmdline_options_t *opt) { @@ -217,7 +221,7 @@ cmdline_options_init(ruby_cmdline_options_t *opt) #elif defined(YJIT_FORCE_ENABLE) opt->features.set |= FEATURE_BIT(yjit); #endif - opt->backtrace_length_limit = -1; + opt->backtrace_length_limit = LONG_MIN; return opt; } @@ -893,7 +897,6 @@ moreswitches(const char *s, ruby_cmdline_options_t *opt, int envopt) VALUE int_enc_name = opt->intern.enc.name; ruby_features_t feat = opt->features; ruby_features_t warn = opt->warn; - int backtrace_length_limit = opt->backtrace_length_limit; while (ISSPACE(*s)) s++; if (!*s) return; @@ -944,9 +947,6 @@ moreswitches(const char *s, ruby_cmdline_options_t *opt, int envopt) } FEATURE_SET_RESTORE(opt->features, feat); FEATURE_SET_RESTORE(opt->warn, warn); - if (backtrace_length_limit >= 0) { - opt->backtrace_length_limit = backtrace_length_limit; - } ruby_xfree(ptr); /* get rid of GC */ @@ -1450,8 +1450,12 @@ proc_long_options(ruby_cmdline_options_t *opt, const char *s, long argc, char ** else if (is_option_with_arg("backtrace-limit", Qfalse, Qtrue)) { char *e; long n = strtol(s, &e, 10); - if (errno == ERANGE || n < -1 || *e) rb_raise(rb_eRuntimeError, "wrong limit for backtrace length"); - opt->backtrace_length_limit = (int)n; + if (errno == ERANGE || !BACKTRACE_LENGTH_LIMIT_VALID_P(n) || *e) { + rb_raise(rb_eRuntimeError, "wrong limit for backtrace length"); + } + else if (!OPT_BACKTRACE_LENGTH_LIMIT_VALID_P(opt)) { + opt->backtrace_length_limit = n; + } } else { rb_raise(rb_eRuntimeError, @@ -2335,7 +2339,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) } if (opt->dump & dump_exit_bits) return Qtrue; - if (opt->backtrace_length_limit >= 0) { + if (OPT_BACKTRACE_LENGTH_LIMIT_VALID_P(opt)) { rb_backtrace_length_limit = opt->backtrace_length_limit; } diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb index c616cb8831..7510505062 100644 --- a/test/ruby/test_rubyoptions.rb +++ b/test/ruby/test_rubyoptions.rb @@ -84,9 +84,14 @@ class TestRubyOptions < Test::Unit::TestCase /^\t \.{3} \d+ levels\.{3}\n/]) assert_kind_of(Integer, Thread::Backtrace.limit) assert_in_out_err(%w(--backtrace-limit=1), "p Thread::Backtrace.limit", ['1'], []) + assert_in_out_err(%w(--backtrace-limit 1), "p Thread::Backtrace.limit", ['1'], []) env = {"RUBYOPT" => "--backtrace-limit=5"} assert_in_out_err([env], "p Thread::Backtrace.limit", ['5'], []) assert_in_out_err([env, "--backtrace-limit=1"], "p Thread::Backtrace.limit", ['1'], []) + assert_in_out_err([env, "--backtrace-limit=-1"], "p Thread::Backtrace.limit", ['-1'], []) + long_max = RbConfig::LIMITS["LONG_MAX"] + assert_in_out_err(%W(--backtrace-limit=#{long_max}), "p Thread::Backtrace.limit", + ["#{long_max}"], []) end def test_warning |