[前][次][番号順一覧][スレッド一覧]

ruby-changes:8684

From: yugui <ko1@a...>
Date: Wed, 12 Nov 2008 00:21:22 +0900 (JST)
Subject: [ruby-changes:8684] Ruby:r20219 (ruby_1_9_1): merges r20053 and r20067 from trunk into ruby_1_9_1.

yugui	2008-11-12 00:21:06 +0900 (Wed, 12 Nov 2008)

  New Revision: 20219

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=20219

  Log:
    merges r20053 and r20067 from trunk into ruby_1_9_1.
    * ruby.c (moreswitches): splits option string and passes arguments.
    * ruby.c (proc_options): checks if allowed in RUBYOPT.
    
    * ruby.c (process_options): allows long style options in RUBYOPT.
    
    * ruby.c (load_file_internal): ditto in shebang.  [ruby-dev:36979]

  Modified files:
    branches/ruby_1_9_1/ChangeLog
    branches/ruby_1_9_1/ruby.c
    branches/ruby_1_9_1/test/ruby/test_rubyoptions.rb

Index: ruby_1_9_1/ChangeLog
===================================================================
--- ruby_1_9_1/ChangeLog	(revision 20218)
+++ ruby_1_9_1/ChangeLog	(revision 20219)
@@ -1,3 +1,18 @@
+Tue Nov 11 23:24:23 2008  Yuki Sonoda (Yugui)  <yugui@y...>
+
+	* ruby.c: merges r20053 and r20067 from trunk into ruby_1_9_1.
+
+	* ruby.c (moreswitches): splits option string and passes arguments.
+
+	* ruby.c (proc_options): checks if allowed in RUBYOPT.
+
+	* ruby.c (process_options): allows long style options in RUBYOPT.
+
+	* ruby.c (load_file_internal): ditto in shebang.  [ruby-dev:36979]
+
+	* ruby.c (process_options): delays setting safe level.
+	  [ruby-dev:36997]
+
 Tue Nov 11 23:36:45 2008  NAKAMURA Usaku  <usa@r...>
 
 	* win32/win32.c (rb_w32_accept): commit miss.
Index: ruby_1_9_1/ruby.c
===================================================================
--- ruby_1_9_1/ruby.c	(revision 20218)
+++ ruby_1_9_1/ruby.c	(revision 20219)
@@ -76,6 +76,7 @@
     unsigned int disable;
     int verbose;
     int yydebug;
+    int safe_level;
     unsigned int setids;
     unsigned int dump;
     const char *script;
@@ -337,9 +338,17 @@
 }
 #endif
 
+void ruby_init_loadpath_safe(int safe_level);
+
 void
 ruby_init_loadpath(void)
 {
+    ruby_init_loadpath_safe(0);
+}
+
+void
+ruby_init_loadpath_safe(int safe_level)
+{
     VALUE load_path;
 #if defined LOAD_RELATIVE
     char libpath[MAXPATHLEN + 1];
@@ -384,7 +393,7 @@
 #define incpush(path) rb_ary_push(load_path, rubylib_mangled_path2(path))
     load_path = GET_VM()->load_path;
 
-    if (rb_safe_level() == 0) {
+    if (safe_level == 0) {
 	ruby_incpush(getenv("RUBYLIB"));
     }
 
@@ -412,7 +421,7 @@
 #endif
     incpush(RUBY_RELATIVE(RUBY_ARCHLIB));
 
-    if (rb_safe_level() == 0) {
+    if (safe_level == 0) {
 	incpush(".");
     }
 }
@@ -514,27 +523,53 @@
 
 NODE *rb_parser_append_print(VALUE, NODE *);
 NODE *rb_parser_while_loop(VALUE, NODE *, int, int);
-static int proc_options(int argc, char **argv, struct cmdline_options *opt);
+static int proc_options(int argc, char **argv, struct cmdline_options *opt, int envopt);
 
-static char *
-moreswitches(const char *s, struct cmdline_options *opt)
+static void
+moreswitches(const char *s, struct cmdline_options *opt, int envopt)
 {
-    int argc;
-    char *argv[3];
-    const char *p = s;
+    int argc, i;
+    char **argv, *p;
+    const char *ap = 0;
+    VALUE argstr, argary;
 
-    argc = 2;
-    argv[0] = argv[2] = 0;
-    while (*s && !ISSPACE(*s))
-	s++;
-    argv[1] = ALLOCA_N(char, s - p + 2);
-    argv[1][0] = '-';
-    strncpy(argv[1] + 1, p, s - p);
-    argv[1][s - p + 1] = '\0';
-    proc_options(argc, argv, opt);
-    while (*s && ISSPACE(*s))
-	s++;
-    return (char *)s;
+    while (ISSPACE(*s)) s++;
+    if (!*s) return;
+    argstr = rb_str_tmp_new(strlen(s) + 2);
+    argary = rb_str_tmp_new(0);
+
+    p = RSTRING_PTR(argstr);
+    *p++ = ' ';
+    strcpy(p, s);
+    ap = 0;
+    rb_str_cat(argary, (char *)&ap, sizeof(ap));
+    while (*p) {
+	ap = p;
+	rb_str_cat(argary, (char *)&ap, sizeof(ap));
+	while (*p && !ISSPACE(*p)) ++p;
+	if (!*p) break;
+	*p++ = '\0';
+	while (ISSPACE(*p)) ++p; 
+    }
+    argc = RSTRING_LEN(argary) / sizeof(ap);
+    ap = 0;
+    rb_str_cat(argary, (char *)&ap, sizeof(ap));
+    argv = (char **)RSTRING_PTR(argary);
+
+    while ((i = proc_options(argc, argv, opt, envopt)) > 1 && (argc -= i) > 0) {
+	argv += i;
+	if (**argv != '-') {
+	    *--*argv = '-';
+	}
+	if ((*argv)[1]) {
+	    ++argc;
+	    --argv;
+	}
+    }
+
+    /* get rid of GC */
+    rb_str_resize(argary, 0);
+    rb_str_resize(argstr, 0);
 }
 
 #define NAME_MATCH_P(name, str, len) \
@@ -619,7 +654,7 @@
 }
 
 static int
-proc_options(int argc, char **argv, struct cmdline_options *opt)
+proc_options(int argc, char **argv, struct cmdline_options *opt, int envopt)
 {
     int n, argc0 = argc;
     const char *s;
@@ -635,14 +670,17 @@
       reswitch:
 	switch (*s) {
 	  case 'a':
+	    if (envopt) goto noenvopt;
 	    opt->do_split = Qtrue;
 	    s++;
 	    goto reswitch;
 
 	  case 'p':
+	    if (envopt) goto noenvopt;
 	    opt->do_print = Qtrue;
 	    /* through */
 	  case 'n':
+	    if (envopt) goto noenvopt;
 	    opt->do_loop = Qtrue;
 	    s++;
 	    goto reswitch;
@@ -654,6 +692,7 @@
 	    goto reswitch;
 
 	  case 'y':
+	    if (envopt) goto noenvopt;
 	    opt->yydebug = 1;
 	    s++;
 	    goto reswitch;
@@ -696,34 +735,40 @@
 	    goto reswitch;
 
 	  case 'c':
+	    if (envopt) goto noenvopt;
 	    opt->do_check = Qtrue;
 	    s++;
 	    goto reswitch;
 
 	  case 's':
+	    if (envopt) goto noenvopt;
 	    forbid_setid("-s");
 	    opt->sflag = 1;
 	    s++;
 	    goto reswitch;
 
 	  case 'h':
+	    if (envopt) goto noenvopt;
 	    usage(origarg.argv[0]);
 	    rb_exit(EXIT_SUCCESS);
 	    break;
 
 	  case 'l':
+	    if (envopt) goto noenvopt;
 	    opt->do_line = Qtrue;
 	    rb_output_rs = rb_rs;
 	    s++;
 	    goto reswitch;
 
 	  case 'S':
+	    if (envopt) goto noenvopt;
 	    forbid_setid("-S");
 	    opt->do_search = Qtrue;
 	    s++;
 	    goto reswitch;
 
 	  case 'e':
+	    if (envopt) goto noenvopt;
 	    forbid_setid("-e");
 	    if (!*++s) {
 		s = argv[1];
@@ -753,11 +798,13 @@
 	    break;
 
 	  case 'i':
+	    if (envopt) goto noenvopt;
 	    forbid_setid("-i");
 	    ruby_set_inplace_mode(s + 1);
 	    break;
 
 	  case 'x':
+	    if (envopt) goto noenvopt;
 	    opt->xflag = Qtrue;
 	    s++;
 	    if (*s && chdir(s) < 0) {
@@ -767,6 +814,7 @@
 
 	  case 'C':
 	  case 'X':
+	    if (envopt) goto noenvopt;
 	    s++;
 	    if (!*s) {
 		s = argv[1];
@@ -781,13 +829,16 @@
 	    break;
 
 	  case 'F':
+	    if (envopt) goto noenvopt;
 	    if (*++s) {
 		rb_fs = rb_reg_new(s, strlen(s), 0);
 	    }
 	    break;
 
 	  case 'E':
-	    if (!*++s) goto next_encoding;
+	    if (!*++s && (!--argc || !(s = *++argv))) {
+		rb_raise(rb_eRuntimeError, "missing argument for -E");
+	    }
 	    goto encoding;
 
 	  case 'U':
@@ -832,7 +883,7 @@
 			v = 1;
 		    s += numlen;
 		}
-		rb_set_safe_level(v);
+		if (v > opt->safe_level) opt->safe_level = v;
 	    }
 	    goto reswitch;
 
@@ -847,6 +898,7 @@
 	    break;
 
 	  case '0':
+	    if (envopt) goto noenvopt;
 	    {
 		int numlen;
 		int v;
@@ -872,35 +924,36 @@
 		goto switch_end;
 	    }
 	    s++;
-	    if (strcmp("copyright", s) == 0)
+
+#	define is_option_end(c, allow_hyphen) \
+	    (!(c) || (allow_hyphen && (c) == '-') || (c) == '=')
+#	define check_envopt(name, allow_envopt) \
+	    ((allow_envopt || !envopt) ? (void)0 : \
+	     rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --" name))
+#	define need_argument(name, s) \
+	    ((*s++ ? !*s : (!--argc || !(s = *++argv))) ?		\
+	     rb_raise(rb_eRuntimeError, "missing argument for --" name) \
+	     : (void)0)
+#	define is_option_with_arg(name, allow_hyphen, allow_envopt) \
+	    (strncmp(name, s, n = sizeof(name) - 1) == 0 && is_option_end(s[n], allow_hyphen) ? \
+	     (check_envopt(name, allow_envopt), s += n, need_argument(name, s), 1) : 0)
+
+	    if (strcmp("copyright", s) == 0) {
+		if (envopt) goto noenvopt_long;
 		opt->copyright = 1;
+	    }
 	    else if (strcmp("debug", s) == 0) {
 		ruby_debug = Qtrue;
                 ruby_verbose = Qtrue;
             }
-	    else if (strncmp("enable", s, n = 6) == 0 &&
-		     (!s[n] || s[n] == '-' || s[n] == '=')) {
-		if ((s += n + 1)[-1] ? !*s : (!--argc || !(s = *++argv))) {
-		    rb_raise(rb_eRuntimeError, "missing argument for --enable");
-		}
+	    else if (is_option_with_arg("enable", Qtrue, Qtrue)) {
 		ruby_each_words(s, enable_option, &opt->disable);
 	    }
-	    else if (strncmp("disable", s, n = 7) == 0 &&
-		     (!s[n] || s[n] == '-' || s[n] == '=')) {
-		if ((s += n + 1)[-1] ? !*s : (!--argc || !(s = *++argv))) {
-		    rb_raise(rb_eRuntimeError, "missing argument for --disable");
-		}
+	    else if (is_option_with_arg("disable", Qtrue, Qtrue)) {
 		ruby_each_words(s, disable_option, &opt->disable);
 	    }
-	    else if (strncmp("encoding", s, n = 8) == 0 && (!s[n] || s[n] == '=')) {
+	    else if (is_option_with_arg("encoding", Qfalse, Qtrue)) {
 		char *p;
-		s += n;
-		if (!*s++) {
-		  next_encoding:
-		    if (!--argc || !(s = *++argv)) {
-			rb_raise(rb_eRuntimeError, "missing argument for --encoding");
-		    }
-		}
 	      encoding:
 		p = strchr(s, ':');
 		if (p) {
@@ -912,19 +965,23 @@
 		else    
 		    set_external_encoding_once(opt, s, 0);
 	    }
-	    else if (strcmp("version", s) == 0)
+	    else if (strcmp("version", s) == 0) {
+		if (envopt) goto noenvopt_long;
 		opt->version = 1;
+	    }
 	    else if (strcmp("verbose", s) == 0) {
 		opt->verbose = 1;
 		ruby_verbose = Qtrue;
 	    }
-	    else if (strcmp("yydebug", s) == 0)
+	    else if (strcmp("yydebug", s) == 0) {
+		if (envopt) goto noenvopt_long;
 		opt->yydebug = 1;
-	    else if (strncmp("dump", s, n = 4) == 0 && (!s[n] || s[n] == '=')) {
-		if (!(s += n + 1)[-1] && (!--argc || !(s = *++argv)) && *s != '-') break;
+	    }
+	    else if (is_option_with_arg("dump", Qfalse, Qfalse)) {
 		ruby_each_words(s, dump_option, &opt->dump);
 	    }
 	    else if (strcmp("help", s) == 0) {
+		if (envopt) goto noenvopt_long;
 		usage(origarg.argv[0]);
 		rb_exit(EXIT_SUCCESS);
 	    }
@@ -953,8 +1010,21 @@
 	    }
 	    goto switch_end;
 
+	  noenvopt:
+	    /* "EIdvwWrKU" only */
+	    rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: -%c", *s);
+	    break;
+
+	  noenvopt_long:
+	    rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --%s", s);
+	    break;
+
 	  case 0:
 	    break;
+#	undef is_option_end
+#	undef check_envopt
+#	undef need_argument
+#	undef is_option_with_arg
 	}
     }
 
@@ -1002,53 +1072,19 @@
     rb_encoding *enc, *lenc;
     const char *s;
     char fbuf[MAXPATHLEN];
-    int i = proc_options(argc, argv, opt);
-    int safe;
+    int i = proc_options(argc, argv, opt, 0);
 
     argc -= i;
     argv += i;
 
     if (!(opt->disable & DISABLE_BIT(rubyopt)) &&
-	rb_safe_level() == 0 && (s = getenv("RUBYOPT"))) {
+	opt->safe_level == 0 && (s = getenv("RUBYOPT"))) {
 	VALUE src_enc_name = opt->src.enc.name;
 	VALUE ext_enc_name = opt->ext.enc.name;
 	VALUE int_enc_name = opt->intern.enc.name;
 
 	opt->src.enc.name = opt->ext.enc.name = opt->intern.enc.name = 0;
-	while (ISSPACE(*s))
-	    s++;
-	if (*s == 'T' || (*s == '-' && *(s + 1) == 'T')) {
-	    int numlen;
-	    int v = 1;
-
-	    if (*s != 'T')
-		++s;
-	    if (*++s) {
-		v = scan_oct(s, 2, &numlen);
-		if (numlen == 0)
-		    v = 1;
-	    }
-	    rb_set_safe_level(v);
-	}
-	else {
-	    while (s && *s) {
-		if (*s == '-') {
-		    s++;
-		    if (ISSPACE(*s)) {
-			do {
-			    s++;
-			} while (ISSPACE(*s));
-			continue;
-		    }
-		}
-		if (!*s)
-		    break;
-		if (!strchr("EIdvwWrKU", *s))
-		    rb_raise(rb_eRuntimeError,
-			     "invalid switch in RUBYOPT: -%c", *s);
-		s = moreswitches(s, opt);
-	    }
-	}
+	moreswitches(s, opt, 1);
 	if (src_enc_name)
 	    opt->src.enc.name = src_enc_name;
 	if (ext_enc_name)
@@ -1065,7 +1101,7 @@
 	ruby_show_copyright();
     }
 
-    if (rb_safe_level() >= 4) {
+    if (opt->safe_level >= 4) {
 	OBJ_TAINT(rb_argv);
 	OBJ_TAINT(GET_VM()->load_path);
     }
@@ -1105,10 +1141,8 @@
 #endif
     opt->script_name = rb_progname;
     opt->script = RSTRING_PTR(opt->script_name);
-    safe = rb_safe_level();
-    rb_set_safe_level_force(0);
 
-    ruby_init_loadpath();
+    ruby_init_loadpath_safe(opt->safe_level);
     ruby_init_gems(!(opt->disable & DISABLE_BIT(gems)));
     lenc = rb_locale_encoding();
     rb_enc_associate(rb_progname, lenc);
@@ -1140,7 +1174,6 @@
     ruby_set_argv(argc, argv);
     process_sflag(opt);
 
-    rb_set_safe_level_force(safe);
     if (opt->e_script) {
 	rb_encoding *eenc;
 	if (opt->src.enc.index >= 0) {
@@ -1174,7 +1207,7 @@
     process_sflag(opt);
     opt->xflag = 0;
 
-    if (rb_safe_level() >= 4) {
+    if (opt->safe_level >= 4) {
 	FL_UNSET(rb_argv, FL_TAINT);
 	FL_UNSET(GET_VM()->load_path, FL_TAINT);
     }
@@ -1200,6 +1233,8 @@
 	return Qtrue;
     }
 
+    rb_set_safe_level(opt->safe_level);
+
     return iseq;
 }
 
@@ -1320,10 +1355,7 @@
 		if (RSTRING_PTR(line)[RSTRING_LEN(line) - 2] == '\r')
 		    RSTRING_PTR(line)[RSTRING_LEN(line) - 2] = '\0';
 		if ((p = strstr(p, " -")) != 0) {
-		    p++;	/* skip space before `-' */
-		    while (*p == '-') {
-			p = moreswitches(p + 1, opt);
-		    }
+		    moreswitches(p + 1, opt, 0);
 		}
 
 		/* push back shebang for pragma may exist in next line */
@@ -1506,7 +1538,7 @@
     if (uid != euid) opt->setids |= 1;
     if (egid != gid) opt->setids |= 2;
     if (uid && opt->setids) {
-	rb_set_safe_level(1);
+	if (opt->safe_level < 1) opt->safe_level = 1;
     }
 }
 
@@ -1518,7 +1550,7 @@
         rb_raise(rb_eSecurityError, "no %s allowed while running setuid", s);
     if (opt->setids & 2)
         rb_raise(rb_eSecurityError, "no %s allowed while running setgid", s);
-    if (rb_safe_level() > 0)
+    if (opt->safe_level > 0)
         rb_raise(rb_eSecurityError, "no %s allowed in tainted mode", s);
 }
 
Index: ruby_1_9_1/test/ruby/test_rubyoptions.rb
===================================================================
--- ruby_1_9_1/test/ruby/test_rubyoptions.rb	(revision 20218)
+++ ruby_1_9_1/test/ruby/test_rubyoptions.rb	(revision 20219)
@@ -199,12 +199,16 @@
     ENV['RUBYOPT'] = ' - -'
     assert_in_out_err([], "", [], [])
 
+    assert_in_out_err(['-e', 'p $:.include?(".")'], "", ["true"], [])
+
     ENV['RUBYOPT'] = '-e "p 1"'
     assert_in_out_err([], "", [], /invalid switch in RUBYOPT: -e \(RuntimeError\)/)
 
     ENV['RUBYOPT'] = '-T1'
     assert_in_out_err([], "", [], /no program input from stdin allowed in tainted mode \(SecurityError\)/)
 
+    assert_in_out_err(['-e', 'p $:.include?(".")'], "", ["false"], [])
+
     ENV['RUBYOPT'] = '-T4'
     assert_in_out_err([], "", [], /no program input from stdin allowed in tainted mode \(SecurityError\)/)
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]