From 2d054e4088982be3266d16dd42a913c7a0884120 Mon Sep 17 00:00:00 2001 From: nagachika Date: Sun, 10 Sep 2017 02:58:23 +0000 Subject: merge revision(s) 59322,59325: [Backport #13744] process.c: handle dynamic :rlimit_* symbols in spawn execopts * process.c (rb_execarg_addopt_rlimit): hoist out of rb_execarg_addopt (rlimit_type_by_sym): new wrapper for dynamic symbol (rb_execarg_addopt): check for dsym via rlimit_type_by_sym * test/ruby/test_process.rb (test_execopts_rlimit): check dsym w/o pindown Add extra check for bogus rlimit args, too. [ruby-core:82033] [Bug #13744] process.c: null bytes * process.c (rlimit_type_by_sym): prohibit null bytes in key names. [ruby-core:82033] [Bug #13744] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_4@59809 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- process.c | 111 ++++++++++++++++++++++++++++------------------ test/ruby/test_process.rb | 16 +++++++ version.h | 2 +- 3 files changed, 86 insertions(+), 43 deletions(-) diff --git a/process.c b/process.c index fe7ebc9b37..18f82ea1e8 100644 --- a/process.c +++ b/process.c @@ -1634,7 +1634,35 @@ check_exec_redirect(VALUE key, VALUE val, struct rb_execarg *eargp) } #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM) -static int rlimit_type_by_lname(const char *name); +static int rlimit_type_by_sym(VALUE key); + +static void +rb_execarg_addopt_rlimit(struct rb_execarg *eargp, int rtype, VALUE val) +{ + VALUE ary = eargp->rlimit_limits; + VALUE tmp, softlim, hardlim; + if (eargp->rlimit_limits == Qfalse) + ary = eargp->rlimit_limits = hide_obj(rb_ary_new()); + else + ary = eargp->rlimit_limits; + tmp = rb_check_array_type(val); + if (!NIL_P(tmp)) { + if (RARRAY_LEN(tmp) == 1) + softlim = hardlim = rb_to_int(rb_ary_entry(tmp, 0)); + else if (RARRAY_LEN(tmp) == 2) { + softlim = rb_to_int(rb_ary_entry(tmp, 0)); + hardlim = rb_to_int(rb_ary_entry(tmp, 1)); + } + else { + rb_raise(rb_eArgError, "wrong exec rlimit option"); + } + } + else { + softlim = hardlim = rb_to_int(val); + } + tmp = hide_obj(rb_ary_new3(3, INT2NUM(rtype), softlim, hardlim)); + rb_ary_push(ary, tmp); +} #endif int @@ -1643,12 +1671,19 @@ rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val) struct rb_execarg *eargp = rb_execarg_get(execarg_obj); ID id; -#if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM) - int rtype; -#endif switch (TYPE(key)) { case T_SYMBOL: +#if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM) + { + int rtype = rlimit_type_by_sym(key); + if (rtype != -1) { + rb_execarg_addopt_rlimit(eargp, rtype, val); + RB_GC_GUARD(execarg_obj); + return ST_CONTINUE; + } + } +#endif if (!(id = rb_check_id(&key))) return ST_STOP; #ifdef HAVE_SETPGID if (id == id_pgroup) { @@ -1680,35 +1715,6 @@ rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val) eargp->new_pgroup_flag = RTEST(val) ? 1 : 0; } else -#endif -#if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM) - if (strncmp("rlimit_", rb_id2name(id), 7) == 0 && - (rtype = rlimit_type_by_lname(rb_id2name(id)+7)) != -1) { - VALUE ary = eargp->rlimit_limits; - VALUE tmp, softlim, hardlim; - if (eargp->rlimit_limits == Qfalse) - ary = eargp->rlimit_limits = hide_obj(rb_ary_new()); - else - ary = eargp->rlimit_limits; - tmp = rb_check_array_type(val); - if (!NIL_P(tmp)) { - if (RARRAY_LEN(tmp) == 1) - softlim = hardlim = rb_to_int(rb_ary_entry(tmp, 0)); - else if (RARRAY_LEN(tmp) == 2) { - softlim = rb_to_int(rb_ary_entry(tmp, 0)); - hardlim = rb_to_int(rb_ary_entry(tmp, 1)); - } - else { - rb_raise(rb_eArgError, "wrong exec rlimit option"); - } - } - else { - softlim = hardlim = rb_to_int(val); - } - tmp = hide_obj(rb_ary_new3(3, INT2NUM(rtype), softlim, hardlim)); - rb_ary_push(ary, tmp); - } - else #endif if (id == id_unsetenv_others) { if (eargp->unsetenv_others_given) { @@ -1811,7 +1817,7 @@ check_exec_options_i(st_data_t st_key, st_data_t st_val, st_data_t arg) VALUE execarg_obj = (VALUE)arg; if (rb_execarg_addopt(execarg_obj, key, val) != ST_CONTINUE) { if (SYMBOL_P(key)) - rb_raise(rb_eArgError, "wrong exec option symbol: %"PRIsVALUE, + rb_raise(rb_eArgError, "wrong exec option symbol: % "PRIsVALUE, key); rb_raise(rb_eArgError, "wrong exec option"); } @@ -4670,13 +4676,13 @@ proc_setpriority(VALUE obj, VALUE which, VALUE who, VALUE prio) #if defined(HAVE_SETRLIMIT) && defined(NUM2RLIM) static int -rlimit_resource_name2int(const char *name, int casetype) +rlimit_resource_name2int(const char *name, long len, int casetype) { int resource; const char *p; #define RESCHECK(r) \ do { \ - if (STRCASECMP(name, #r) == 0) { \ + if (len == rb_strlen_lit(#r) && STRCASECMP(name, #r) == 0) { \ resource = RLIMIT_##r; \ goto found; \ } \ @@ -4779,21 +4785,40 @@ rlimit_resource_name2int(const char *name, int casetype) } static int -rlimit_type_by_hname(const char *name) +rlimit_type_by_hname(const char *name, long len) { - return rlimit_resource_name2int(name, 0); + return rlimit_resource_name2int(name, len, 0); } static int -rlimit_type_by_lname(const char *name) +rlimit_type_by_lname(const char *name, long len) { - return rlimit_resource_name2int(name, 1); + return rlimit_resource_name2int(name, len, 1); +} + +static int +rlimit_type_by_sym(VALUE key) +{ + VALUE name = rb_sym2str(key); + const char *rname = RSTRING_PTR(name); + long len = RSTRING_LEN(name); + int rtype = -1; + static const char prefix[] = "rlimit_"; + enum {prefix_len = sizeof(prefix)-1}; + + if (len > prefix_len && strncmp(prefix, rname, prefix_len) == 0) { + rtype = rlimit_type_by_lname(rname + prefix_len, len - prefix_len); + } + + RB_GC_GUARD(key); + return rtype; } static int rlimit_resource_type(VALUE rtype) { const char *name; + long len; VALUE v; int r; @@ -4801,6 +4826,7 @@ rlimit_resource_type(VALUE rtype) case T_SYMBOL: v = rb_sym2str(rtype); name = RSTRING_PTR(v); + len = RSTRING_LEN(v); break; default: @@ -4809,6 +4835,7 @@ rlimit_resource_type(VALUE rtype) rtype = v; case T_STRING: name = StringValueCStr(rtype); + len = RSTRING_LEN(rtype); break; } /* fall through */ @@ -4818,11 +4845,11 @@ rlimit_resource_type(VALUE rtype) return NUM2INT(rtype); } - r = rlimit_type_by_hname(name); + r = rlimit_type_by_hname(name, len); if (r != -1) return r; - rb_raise(rb_eArgError, "invalid resource name: %"PRIsVALUE, rtype); + rb_raise(rb_eArgError, "invalid resource name: % "PRIsVALUE, rtype); UNREACHABLE; } diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb index cd45bde99d..f3d02f3bee 100644 --- a/test/ruby/test_process.rb +++ b/test/ruby/test_process.rb @@ -242,6 +242,22 @@ class TestProcess < Test::Unit::TestCase :rlimit_core=>n, :rlimit_cpu=>3600]) {|io| assert_equal("[#{n}, #{n}]\n[3600, 3600]", io.read.chomp) } + + assert_raise(ArgumentError) do + system(RUBY, '-e', 'exit', 'rlimit_bogus'.to_sym => 123) + end + assert_separately([],<<-"end;") # [ruby-core:82033] [Bug #13744] + assert(system("#{RUBY}", "-e", + "exit([3600,3600] == Process.getrlimit(:CPU))", + 'rlimit_cpu'.to_sym => 3600)) + assert_raise(ArgumentError) do + system("#{RUBY}", '-e', 'exit', :rlimit_bogus => 123) + end + end; + + assert_raise(ArgumentError, /rlimit_cpu/) { + system(RUBY, '-e', 'exit', "rlimit_cpu\0".to_sym => 3600) + } end MANDATORY_ENVS = %w[RUBYLIB] diff --git a/version.h b/version.h index 868460a26f..e633964874 100644 --- a/version.h +++ b/version.h @@ -1,6 +1,6 @@ #define RUBY_VERSION "2.4.2" #define RUBY_RELEASE_DATE "2017-09-10" -#define RUBY_PATCHLEVEL 186 +#define RUBY_PATCHLEVEL 187 #define RUBY_RELEASE_YEAR 2017 #define RUBY_RELEASE_MONTH 9 -- cgit v1.2.3