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/