[ruby-dev:21363] Re: $SAFE=4 でのautoload
From:
nobu.nakada@...
Date:
2003-09-08 14:19:07 UTC
List:
ruby-dev #21363
なかだです。
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はできる。
中田 伸悦