From: Nobuyoshi Nakada Date: 2008-04-16T18:26:20+09:00 Subject: [ruby-dev:34427] Re: can't start ruby with RUBYOPT=-T4 なかだです。 At Wed, 16 Apr 2008 12:49:39 +0900, Yusuke ENDOH wrote in [ruby-dev:34421]: > r16050 で修正していただいたようですが、その副作用で RUBYOPT=-T1 > でも標準入力からプログラムを流し込めるようになったようです。 > > $ RUBYOPT=-T1 ./ruby > p 1 > 1 encodingは常に$SAFE=0でロードするようにしようかとも思いましたが、 その場合は通常のライブラリとは分けないとまずいかなという気もしま す。 もう一つ考えたのが、-Tの影響を process_optionsの中に閉じてしまっ て、実際に$SAFEにセットするのは最後に回す、という方法です。 Index: parse.y =================================================================== --- parse.y (revision 16050) +++ parse.y (working copy) @@ -8691,4 +8691,24 @@ rb_gc_mark_parser(void) NODE* +rb_parser_add_prelude(VALUE vparser, NODE *node, NODE *prelude) +{ + NODE *scope = node; + struct parser_params *parser; + + Data_Get_Struct(vparser, struct parser_params, parser); + + node = node->nd_body; + + if (nd_type(node) == NODE_PRELUDE) { + node->nd_head = block_append(prelude, node->nd_head); + } + else { + scope->nd_body = NEW_PRELUDE(prelude, scope->nd_body); + } + + return scope; +} + +NODE* rb_parser_append_print(VALUE vparser, NODE *node) { Index: ruby.c =================================================================== --- ruby.c (revision 16050) +++ ruby.c (working copy) @@ -84,4 +95,6 @@ struct cmdline_options { int verbose; int yydebug; + int safe_level; + unsigned int setids; char *script; VALUE script_name; @@ -93,6 +107,12 @@ struct cmdline_options { } enc; } src, ext; }; +static void init_ids(struct cmdline_options *); + +#define cmdline_options_init(opt) (MEMZERO((opt), *(opt), 1), \ + init_ids(opt), \ + (opt)->src.enc.index = src_encoding_index) + struct cmdline_arguments { int argc; @@ -102,5 +126,6 @@ struct cmdline_arguments { static NODE *load_file(VALUE, const char *, int, struct cmdline_options *); -static void forbid_setid(const char *); +static void forbid_setid(const char *, struct cmdline_options *); +#define forbid_setid(s) forbid_setid(s, opt) static struct { @@ -328,5 +353,5 @@ DllMain(HINSTANCE dll, DWORD reason, LPV void -ruby_init_loadpath(void) +ruby_init_loadpath_safe(int safe_level) { #if defined LOAD_RELATIVE @@ -378,5 +404,5 @@ ruby_init_loadpath(void) #define incpush(path) rb_ary_push(rb_load_path, rubylib_mangled_path2(path)) - if (rb_safe_level() == 0) { + if (safe_level == 0) { ruby_incpush(getenv("RUBYLIB")); } @@ -406,8 +432,14 @@ ruby_init_loadpath(void) incpush(RUBY_RELATIVE(RUBY_ARCHLIB)); - if (rb_safe_level() == 0) { + if (safe_level == 0) { incpush("."); } } + +void +ruby_init_loadpath(void) +{ + ruby_init_loadpath_safe(rb_safe_level()); +} struct req_list { @@ -793,5 +825,5 @@ proc_options(int argc, char **argv, stru s += numlen; } - rb_set_safe_level(v); + if (v > opt->safe_level) opt->safe_level = v; } goto reswitch; @@ -939,4 +975,5 @@ VALUE rb_progname; VALUE rb_argv0; static int src_encoding_index = -1; /* TODO: VM private */ +NODE *rb_parser_add_prelude(VALUE vparser, NODE *node, NODE *prelude); static VALUE @@ -949,8 +986,8 @@ process_options(VALUE arg) NODE *tree = 0; VALUE parser; + VALUE iseq; rb_encoding *enc; const char *s; int i = proc_options(argc, argv, opt); - int safe; argc -= i; @@ -958,5 +995,5 @@ process_options(VALUE arg) 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; @@ -975,5 +1012,5 @@ process_options(VALUE arg) v = 1; } - rb_set_safe_level(v); + if (v > opt->safe_level) opt->safe_level = v; } else { @@ -1010,5 +1047,5 @@ process_options(VALUE arg) } - if (rb_safe_level() >= 4) { + if (opt->safe_level >= 4) { OBJ_TAINT(rb_argv); OBJ_TAINT(rb_load_path); @@ -1053,7 +1090,5 @@ process_options(VALUE arg) process_sflag(opt); - ruby_init_loadpath(); - safe = rb_safe_level(); - rb_set_safe_level_force(0); + ruby_init_loadpath_safe(opt->safe_level); ruby_init_gems(!(opt->disable & DISABLE_BIT(gems))); parser = rb_parser_new(); @@ -1092,5 +1127,4 @@ process_options(VALUE arg) tree = load_file(parser, opt->script, 1, opt); } - rb_set_safe_level_force(safe); if (!tree) return Qfalse; @@ -1099,5 +1133,5 @@ process_options(VALUE arg) opt->xflag = 0; - if (rb_safe_level() >= 4) { + if (opt->safe_level >= 4) { FL_UNSET(rb_argv, FL_TAINT); FL_UNSET(rb_load_path, FL_TAINT); @@ -1116,6 +1150,10 @@ process_options(VALUE arg) } - return rb_iseq_new(tree, rb_str_new2("
"), + iseq = rb_iseq_new(tree, rb_str_new2("
"), opt->script_name, Qfalse, ISEQ_TYPE_TOP); + + rb_set_safe_level(opt->safe_level); + + return iseq; } @@ -1274,6 +1318,5 @@ rb_load_file(const char *fname) struct cmdline_options opt; - MEMZERO(&opt, opt, 1); - opt.src.enc.index = src_encoding_index; + cmdline_options_init(&opt); return load_file(rb_parser_new(), fname, 0, &opt); } @@ -1379,30 +1422,31 @@ ruby_script(const char *name) } -static int uid, euid, gid, egid; - static void -init_ids(void) +init_ids(struct cmdline_options *opt) { - uid = (int)getuid(); - euid = (int)geteuid(); - gid = (int)getgid(); - egid = (int)getegid(); + rb_uid_t uid = getuid(); + rb_uid_t euid = geteuid(); + rb_gid_t gid = getgid(); + rb_gid_t egid = getegid(); #ifdef VMS uid |= gid << 16; euid |= egid << 16; #endif - if (uid && (euid != uid || egid != gid)) { - rb_set_safe_level(1); + if (euid != uid) opt->setids |= 1; + if (egid != gid) opt->setids |= 2; + if (uid && opt->setids) { + opt->safe_level = 1; } } +#undef forbid_setid static void -forbid_setid(const char *s) +forbid_setid(const char *s, struct cmdline_options *opt) { - if (euid != uid) + if (opt->setids & 1) rb_raise(rb_eSecurityError, "no %s allowed while running setuid", s); - if (egid != gid) + 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); } @@ -1429,6 +1473,4 @@ void ruby_prog_init(void) { - init_ids(); - rb_define_hooked_variable("$VERBOSE", &ruby_verbose, 0, verbose_setter); rb_define_hooked_variable("$-v", &ruby_verbose, 0, verbose_setter); @@ -1497,5 +1539,5 @@ ruby_process_options(int argc, char **ar NODE *tree; - MEMZERO(&opt, opt, 1); + cmdline_options_init(&opt); ruby_script(argv[0]); /* for the time being */ rb_argv0 = rb_progname; @@ -1503,5 +1545,4 @@ ruby_process_options(int argc, char **ar args.argv = argv; args.opt = &opt; - opt.src.enc.index = src_encoding_index; opt.ext.enc.index = -1; tree = (NODE *)rb_vm_call_cfunc(rb_vm_top_self(), -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦