From: nobu.nakada@... Date: 2003-09-08T23:19:07+09:00 Subject: [ruby-dev:21363] Re: $SAFE=4 でのautoload なかだです。 At Sat, 6 Sep 2003 22:16:02 +0900, Yukihiro Matsumoto wrote: > |> そうすると、requireはautoloadを呼び出したときの$SAFEで実行すべ > |> きでしょうか。もしそうだとすれば、今はすでにautoloadされている > |> 定数をさらにautoloadしようとしても何も変わりませんが、違う$SAFE > |> で呼ばれたときにはどっちを優先すべきなんでしょう。 > | > |autoload を呼んで対応付けをしたときの $SAFE とすべきではないかと > |思うのですが,何かまずいでしょうか. > > まずくないです。autoloadでもrequreと同様に実行前に$SAFEを0に > セットする必要があるでしょうね。 0? autoloadを呼んだときの$SAFE? とりあえず、最初にautoloadを呼んだときのを優先するようにしてみ ました。 * rb_feature_p: 外部にアクセスしないようにする。 拡張ライブラリとスクリプトの区別は、rb_featuresの拡張子の分類 だけに。 * rb_require_0: $SAFEを指定できるようにする。 Index: eval.c =================================================================== RCS file: /cvs/ruby/src/ruby/eval.c,v retrieving revision 1.531 diff -u -2 -p -r1.531 eval.c --- eval.c 5 Sep 2003 05:07:54 -0000 1.531 +++ eval.c 8 Sep 2003 10:27:56 -0000 @@ -5839,41 +5836,56 @@ rb_feature_p(feature, wait) { VALUE v; - char *f; + char *f, *ext = strrchr(feature, '.'); long i, len = strlen(feature); + int rb = 1, so = 1; + if (ext && !strchr(ext, '/')) { + if (strcmp(ext, ".rb") == 0) { + so = 0; + len = ext - feature; + } + else if (strcmp(ext, ".so") == 0 || strcmp(ext, ".o") == 0 || +#ifdef DLEXT2 + strcmp(ext, DLEXT2) == 0 || +#endif + strcmp(ext, DLEXT) == 0) { + rb = 0; + len = ext - feature; + } + } for (i = 0; i < RARRAY(rb_features)->len; ++i) { v = RARRAY(rb_features)->ptr[i]; f = StringValuePtr(v); - if (strcmp(f, feature) == 0) { - goto load_wait; + if (strncmp(f, feature, len) != 0) continue; + ext = f + len; + if (!*ext) { + if (feature[len]) continue; + return Qtrue; } - if (strncmp(f, feature, len) == 0) { - if (strcmp(f+len, ".so") == 0) { - return Qtrue; - } - if (strcmp(f+len, ".rb") == 0) { - if (wait) goto load_wait; + if (so) { + if (strcmp(ext, ".so") == 0 || strcmp(ext, ".o") == 0 || +#ifdef DLEXT2 + strcmp(ext, DLEXT2) == 0 || +#endif + strcmp(ext, DLEXT) == 0) { return Qtrue; } } - } - return Qfalse; - - load_wait: - if (loading_tbl) { - char *ext = strrchr(f, '.'); - if (ext && strcmp(ext, ".rb") == 0) { - rb_thread_t th; - - while (st_lookup(loading_tbl, (st_data_t)f, (st_data_t *)&th)) { - if (th == curr_thread) { - return Qtrue; + if (rb) { + if (strcmp(ext, ".rb") == 0) { + if (wait && loading_tbl) { + st_data_t th; + + while (st_lookup(loading_tbl, (st_data_t)f, &th)) { + if ((rb_thread_t)th == curr_thread) break; + CHECK_INTS; + rb_thread_schedule(); + } } - CHECK_INTS; - rb_thread_schedule(); + return Qtrue; } } } - return Qtrue; + return Qfalse; } @@ -5890,12 +5902,5 @@ rb_provided(feature) const char *feature; { - VALUE f = rb_str_new2(feature); - - if (strrchr(feature, '.') == 0) { - if (rb_find_file_ext(&f, loadable_ext) == 0) { - return rb_feature_p(feature, Qfalse); - } - } - return rb_feature_p(RSTRING(f)->ptr, Qfalse); + return rb_feature_p(feature, Qfalse); } @@ -5914,149 +5919,138 @@ rb_provide(feature) } -NORETURN(static void load_failed _((VALUE))); -static VALUE load_dyna _((VALUE, VALUE)); -static VALUE load_rb _((VALUE, VALUE)); - -VALUE -rb_f_require(obj, fname) - VALUE obj, fname; +static VALUE +rb_require_0(fname, safe) + VALUE fname; + int safe; { - VALUE feature, tmp; char *ext; /* OK */ + int state; + struct { + NODE *node; + ID func; + int vmode, safe; + } volatile save; + char *volatile ftptr = 0; + volatile VALUE failed = 0; - SafeStringValue(fname); + StringValue(fname); + if (rb_feature_p(RSTRING(fname)->ptr, Qfalse)) + return Qfalse; ext = strrchr(RSTRING(fname)->ptr, '.'); - if (ext && strchr(ext, '/')) ext = 0; - if (ext) { - if (strcmp(".rb", ext) == 0) { - feature = rb_str_dup(fname); - tmp = rb_find_file(fname); - if (tmp) { - return load_rb(feature, tmp); + save.vmode = scope_vmode; + save.node = ruby_current_node; + save.func = ruby_frame->last_func; + save.safe = ruby_safe_level; + PUSH_TAG(PROT_NONE); + if ((state = EXEC_TAG()) == 0) { + VALUE feature, tmp; + + ruby_safe_level = safe; + if (ext && !strchr(ext, '/')) { + if (strcmp(".rb", ext) == 0) { + feature = rb_str_dup(fname); + tmp = rb_find_file(fname); + if (tmp) { + goto load_rb; + } + goto load_failed; } - load_failed(fname); - } - else if (strcmp(".so", ext) == 0 || strcmp(".o", ext) == 0) { - tmp = rb_str_new(RSTRING(fname)->ptr, ext-RSTRING(fname)->ptr); + else if (strcmp(".so", ext) == 0 || strcmp(".o", ext) == 0) { + tmp = rb_str_new(RSTRING(fname)->ptr, ext-RSTRING(fname)->ptr); #ifdef DLEXT2 - if (rb_find_file_ext(&tmp, loadable_ext+1)) { - return load_dyna(tmp, rb_find_file(tmp)); - } + if (rb_find_file_ext(&tmp, loadable_ext+1)) { + feature = tmp; + tmp = rb_find_file(tmp); + goto load_dyna; + } #else - feature = tmp; - rb_str_cat2(tmp, DLEXT); - tmp = rb_find_file(tmp); - if (tmp) { - return load_dyna(feature, tmp); - } + feature = tmp; + rb_str_cat2(tmp, DLEXT); + tmp = rb_find_file(tmp); + if (tmp) { + goto load_dyna; + } #endif - } - else if (strcmp(DLEXT, ext) == 0) { - tmp = rb_find_file(fname); - if (tmp) { - return load_dyna(fname, tmp); } - } + else if (strcmp(DLEXT, ext) == 0) { + tmp = rb_find_file(fname); + if (tmp) { + feature = fname; + goto load_dyna; + } + } #ifdef DLEXT2 - else if (strcmp(DLEXT2, ext) == 0) { - tmp = rb_find_file(fname); - if (tmp) { - return load_dyna(fname, tmp); + else if (strcmp(DLEXT2, ext) == 0) { + tmp = rb_find_file(fname); + if (tmp) { + feature = fname; + goto load_dyna; + } } - } #endif - } - tmp = fname; - switch (rb_find_file_ext(&tmp, loadable_ext)) { - case 0: - break; - - case 1: - return load_rb(tmp, tmp); - - default: - return load_dyna(tmp, rb_find_file(tmp)); - } - if (!rb_feature_p(RSTRING(fname)->ptr, Qfalse)) - load_failed(fname); - return Qfalse; -} - -static void -load_failed(fname) - VALUE fname; -{ - rb_raise(rb_eLoadError, "No such file to load -- %s", RSTRING(fname)->ptr); -} - -static VALUE -load_dyna(feature, fname) - VALUE feature, fname; -{ - int state; + } + tmp = fname; + switch (rb_find_file_ext(&tmp, loadable_ext)) { + case 0: + load_failed: + failed = fname; + break; - if (rb_feature_p(RSTRING(feature)->ptr, Qfalse)) - return Qfalse; - rb_provide_feature(feature); - { - int volatile old_vmode = scope_vmode; - NODE *const volatile old_node = ruby_current_node; - const volatile ID old_func = ruby_frame->last_func; - - ruby_current_node = 0; - ruby_sourcefile = rb_source_filename(RSTRING(fname)->ptr); - ruby_sourceline = 0; - ruby_frame->last_func = 0; - PUSH_TAG(PROT_NONE); - if ((state = EXEC_TAG()) == 0) { - void *handle; + case 1: + feature = tmp; + load_rb: + rb_provide_feature(feature); + /* loading ruby library should be serialized. */ + if (!loading_tbl) { + loading_tbl = st_init_strtable(); + } + /* partial state */ + ftptr = ruby_strdup(RSTRING(feature)->ptr); + st_insert(loading_tbl, (st_data_t)ftptr, (st_data_t)curr_thread); + rb_load(tmp, 0); + break; + default: + feature = tmp; + tmp = rb_find_file(tmp); + load_dyna: + rb_provide_feature(feature); + ruby_current_node = 0; + ruby_sourcefile = rb_source_filename(RSTRING(tmp)->ptr); + ruby_sourceline = 0; + ruby_frame->last_func = 0; SCOPE_SET(SCOPE_PUBLIC); - handle = dln_load(RSTRING(fname)->ptr); - rb_ary_push(ruby_dln_librefs, LONG2NUM((long)handle)); + { + void *handle = dln_load(RSTRING(tmp)->ptr); + rb_ary_push(ruby_dln_librefs, LONG2NUM((long)handle)); + } + break; } - POP_TAG(); - ruby_current_node = old_node; - ruby_set_current_source(); - ruby_frame->last_func = old_func; - SCOPE_SET(old_vmode); + } + POP_TAG(); + ruby_safe_level = save.safe; + ruby_current_node = save.node; + ruby_set_current_source(); + ruby_frame->last_func = save.func; + SCOPE_SET(save.vmode); + if (ftptr) { + st_delete(loading_tbl, (st_data_t *)&ftptr, 0); /* loading done */ + free(ftptr); } if (state) JUMP_TAG(state); ruby_errinfo = Qnil; - return Qtrue; + if (fname = failed) { + rb_raise(rb_eLoadError, "No such file to load -- %s", + RSTRING(fname)->ptr); + } + return Qfalse; } -static VALUE -load_rb(feature, fname) - VALUE feature, fname; +VALUE +rb_f_require(obj, fname) + VALUE obj, fname; { - int state; - char *ftptr; - volatile int safe = ruby_safe_level; - - if (rb_feature_p(RSTRING(feature)->ptr, Qtrue)) - return Qfalse; - ruby_safe_level = 0; - rb_provide_feature(feature); - /* loading ruby library should be serialized. */ - if (!loading_tbl) { - loading_tbl = st_init_strtable(); - } - /* partial state */ - ftptr = ruby_strdup(RSTRING(feature)->ptr); - st_insert(loading_tbl, (st_data_t)ftptr, (st_data_t)curr_thread); - - PUSH_TAG(PROT_NONE); - if ((state = EXEC_TAG()) == 0) { - rb_load(fname, 0); - } - POP_TAG(); - st_delete(loading_tbl, (st_data_t *)&ftptr, 0); /* loading done */ - free(ftptr); - ruby_safe_level = safe; - if (state) JUMP_TAG(state); - - return Qtrue; + return rb_require_0(fname, ruby_safe_level); } @@ -6065,5 +6059,19 @@ rb_require(fname) const char *fname; { - return rb_f_require(Qnil, rb_str_new2(fname)); + return rb_require_0(rb_str_new2(fname), ruby_safe_level); +} + +void +rb_require_autoload(file, safe, klass, id) + VALUE file; + int safe; + VALUE klass; + ID id; +{ + PUSH_FRAME(); + ruby_frame->last_class = klass; + ruby_frame->last_func = id; + rb_require_0(file, safe); + POP_FRAME(); } Index: variable.c =================================================================== RCS file: /cvs/ruby/src/ruby/variable.c,v retrieving revision 1.102 diff -u -2 -p -r1.102 variable.c --- variable.c 30 Aug 2003 00:03:57 -0000 1.102 +++ variable.c 8 Sep 2003 02:17:01 -0000 @@ -1147,5 +1147,5 @@ rb_autoload(mod, id, file) const char *file; { - VALUE av; + VALUE av, fn; struct st_table *tbl; @@ -1171,5 +1171,8 @@ rb_autoload(mod, id, file) DATA_PTR(av) = tbl = st_init_numtable(); } - st_insert(tbl, id, rb_str_new2(file)); + fn = rb_str_new2(file); + FL_UNSET(fn, FL_TAINT); + OBJ_FREEZE(fn); + st_insert(tbl, id, rb_assoc_new(fn, INT2FIX(ruby_safe_level))); } @@ -1205,12 +1208,12 @@ rb_autoload_load(klass, id) ID id; { - VALUE file; + VALUE av; - file = autoload_delete(klass, id); - if (NIL_P(file) || rb_provided(RSTRING(file)->ptr)) { + av = autoload_delete(klass, id); + if (NIL_P(av) || rb_provided(RSTRING(RARRAY(av)->ptr[0])->ptr)) { const_missing(klass, id); } - FL_UNSET(file, FL_TAINT); - rb_f_require(Qnil, file); + rb_require_autoload(RARRAY(av)->ptr[0], FIX2INT(RARRAY(av)->ptr[1]), + klass, id); } @@ -1220,11 +1223,13 @@ autoload_file(mod, id) ID id; { - VALUE val, file; + VALUE val, av, file; struct st_table *tbl; if (!st_lookup(RCLASS(mod)->iv_tbl, autoload, &val) || - !(tbl = check_autoload_table(val)) || !st_lookup(tbl, id, &file)) { + !(tbl = check_autoload_table(val)) || !st_lookup(tbl, id, &av)) { return Qnil; } + Check_Type(av, T_ARRAY); + file = RARRAY(av)->ptr[0]; Check_Type(file, T_STRING); if (!RSTRING(file)->ptr) { -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦