summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-09-10 02:58:23 +0000
committernagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-09-10 02:58:23 +0000
commit2d054e4088982be3266d16dd42a913c7a0884120 (patch)
tree299f0b658d7bf26eb345990c3eeba77094de2bcc
parent428687e96d9e58c13ebcbbfb4411f1edba71fcc5 (diff)
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
-rw-r--r--process.c111
-rw-r--r--test/ruby/test_process.rb16
-rw-r--r--version.h2
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) {
@@ -1681,35 +1716,6 @@ rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val)
}
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) {
rb_raise(rb_eArgError, "unsetenv_others option specified twice");
@@ -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