1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* eval.c (rb_feature_p): match by classified suffix.

* eval.c (rb_require_safe): require library in the specified safe
  level.

* variable.c (rb_autoload, rb_autoload_load): restore safe level
  when autoload was called.  [ruby-dev:21338]

* intern.h: prototypes; rb_require_safe.

* test/runner.rb: accept non-option arguments.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4751 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2003-10-13 14:57:36 +00:00
parent 1b8c124c8d
commit 4de0bb549b
5 changed files with 203 additions and 162 deletions

View file

@ -1,3 +1,19 @@
Mon Oct 13 23:57:29 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
* eval.c (rb_feature_p): match by classified suffix.
* eval.c (rb_require_safe): require library in the specified safe
level.
* variable.c (rb_autoload, rb_autoload_load): restore safe level
when autoload was called. [ruby-dev:21338]
* intern.h: prototypes; rb_require_safe.
Mon Oct 13 23:57:29 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
* test/runner.rb: accept non-option arguments.
Mon Oct 13 20:49:51 2003 Yukihiro Matsumoto <matz@ruby-lang.org> Mon Oct 13 20:49:51 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
* string.c (str_new4): should not preserve FL_TAINT status in the * string.c (str_new4): should not preserve FL_TAINT status in the

288
eval.c
View file

@ -5739,6 +5739,8 @@ rb_mod_module_eval(argc, argv, mod)
VALUE rb_load_path; VALUE rb_load_path;
NORETURN(static void load_failed _((VALUE)));
void void
rb_load(fname, wrap) rb_load(fname, wrap)
VALUE fname; VALUE fname;
@ -5761,7 +5763,7 @@ rb_load(fname, wrap)
} }
tmp = rb_find_file(fname); tmp = rb_find_file(fname);
if (!tmp) { if (!tmp) {
rb_raise(rb_eLoadError, "No such file to load -- %s", RSTRING(fname)->ptr); load_failed(fname);
} }
fname = tmp; fname = tmp;
@ -5871,49 +5873,47 @@ VALUE ruby_dln_librefs;
static VALUE rb_features; static VALUE rb_features;
static st_table *loading_tbl; static st_table *loading_tbl;
static int #define IS_SOEXT(e) (strcmp(e, ".so") == 0 || strcmp(e, ".o") == 0)
rb_feature_p(feature, wait) #ifdef DLEXT2
const char *feature; #define IS_DLEXT(e) (strcmp(e, DLEXT) == 0 || strcmp(e, DLEXT2) == 0)
int wait; #else
#define IS_DLEXT(e) (strcmp(e, DLEXT) == 0)
#endif
static char *
rb_feature_p(feature, ext, rb)
const char *feature, *ext;
int rb;
{ {
VALUE v; VALUE v;
char *f; char *f, *e;
long i, len = strlen(feature); long i, len, elen;
if (ext) {
len = ext - feature;
elen = strlen(ext);
}
else {
len = strlen(feature);
elen = 0;
}
for (i = 0; i < RARRAY(rb_features)->len; ++i) { for (i = 0; i < RARRAY(rb_features)->len; ++i) {
v = RARRAY(rb_features)->ptr[i]; v = RARRAY(rb_features)->ptr[i];
f = StringValuePtr(v); f = StringValuePtr(v);
if (strcmp(f, feature) == 0) { if (strncmp(f, feature, len) != 0) continue;
goto load_wait; if (!*(e = f + len)) {
if (ext) continue;
return e;
} }
if (strncmp(f, feature, len) == 0) { if (*e != '.') continue;
if (strcmp(f+len, ".so") == 0) { if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) {
return Qtrue; return e;
} }
if (strcmp(f+len, ".rb") == 0) { if ((rb || !ext) && (strcmp(e, ".rb") == 0)) {
if (wait) goto load_wait; return e;
return Qtrue;
} }
} }
} return 0;
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;
}
CHECK_INTS;
rb_thread_schedule();
}
}
}
return Qtrue;
} }
static const char *const loadable_ext[] = { static const char *const loadable_ext[] = {
@ -5928,14 +5928,7 @@ int
rb_provided(feature) rb_provided(feature)
const char *feature; const char *feature;
{ {
VALUE f = rb_str_new2(feature); return rb_feature_p(feature, 0, Qfalse) ? Qtrue : Qfalse;
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);
} }
static void static void
@ -5952,76 +5945,83 @@ rb_provide(feature)
rb_provide_feature(rb_str_new2(feature)); rb_provide_feature(rb_str_new2(feature));
} }
NORETURN(static void load_failed _((VALUE))); static void
static VALUE load_dyna _((VALUE, VALUE)); load_wait(ftptr)
static VALUE load_rb _((VALUE, VALUE)); char *ftptr;
{
st_data_t th;
if (!loading_tbl) return;
if (!st_lookup(loading_tbl, (st_data_t)ftptr, &th)) return;
if ((rb_thread_t)th == curr_thread) return;
do {
CHECK_INTS;
rb_thread_schedule();
} while (st_lookup(loading_tbl, (st_data_t)ftptr, &th));
}
VALUE VALUE
rb_f_require(obj, fname) rb_f_require(obj, fname)
VALUE obj, fname; VALUE obj, fname;
{ {
VALUE feature, tmp; return rb_require_safe(fname, ruby_safe_level);
char *ext; /* OK */ }
if (OBJ_TAINTED(fname)) { static int
rb_check_safe_obj(fname); search_required(fname, featurep, path)
} VALUE fname, *featurep, *path;
StringValue(fname); {
ext = strrchr(RSTRING(fname)->ptr, '.'); VALUE tmp;
if (ext && strchr(ext, '/')) ext = 0; char *ext, *ftptr;
if (ext) {
*featurep = fname;
*path = 0;
ext = strrchr(ftptr = RSTRING(fname)->ptr, '.');
if (ext && !strchr(ext, '/')) {
if (strcmp(".rb", ext) == 0) { if (strcmp(".rb", ext) == 0) {
feature = rb_str_dup(fname); if (rb_feature_p(ftptr, ext, Qtrue)) return 'r';
tmp = rb_find_file(fname); if (*path = rb_find_file(fname)) return 'r';
if (tmp) { return 0;
return load_rb(feature, tmp);
} }
load_failed(fname); else if (IS_SOEXT(ext)) {
} if (rb_feature_p(ftptr, ext, Qfalse)) return 's';
else if (strcmp(".so", ext) == 0 || strcmp(".o", ext) == 0) {
tmp = rb_str_new(RSTRING(fname)->ptr, ext-RSTRING(fname)->ptr); tmp = rb_str_new(RSTRING(fname)->ptr, ext-RSTRING(fname)->ptr);
*featurep = tmp;
#ifdef DLEXT2 #ifdef DLEXT2
if (rb_find_file_ext(&tmp, loadable_ext+1)) { if (rb_find_file_ext(&tmp, loadable_ext+1)) {
return load_dyna(tmp, rb_find_file(tmp)); *path = rb_find_file(tmp);
return 's';
} }
#else #else
feature = tmp;
rb_str_cat2(tmp, DLEXT); rb_str_cat2(tmp, DLEXT);
tmp = rb_find_file(tmp); if (*path = rb_find_file(tmp)) {
if (tmp) { return 's';
return load_dyna(feature, tmp);
} }
#endif #endif
} }
else if (strcmp(DLEXT, ext) == 0) { else if (IS_DLEXT(ext)) {
tmp = rb_find_file(fname); if (rb_feature_p(ftptr, ext, Qfalse)) return 's';
if (tmp) { if (*path = rb_find_file(fname)) return 's';
return load_dyna(fname, tmp);
} }
} }
#ifdef DLEXT2 if ((ext = rb_feature_p(ftptr, 0, Qfalse)) != 0) {
else if (strcmp(DLEXT2, ext) == 0) { return strcmp(ext, ".rb") == 0 ? 'r' : 's';
tmp = rb_find_file(fname);
if (tmp) {
return load_dyna(fname, tmp);
}
}
#endif
} }
tmp = fname; tmp = fname;
switch (rb_find_file_ext(&tmp, loadable_ext)) { switch (rb_find_file_ext(&tmp, loadable_ext)) {
case 0: case 0:
break; return 0;
case 1: case 1:
return load_rb(tmp, tmp); *featurep = tmp;
*path = rb_find_file(tmp);
return 'r';
default: default:
return load_dyna(tmp, rb_find_file(tmp)); *featurep = tmp;
*path = rb_find_file(tmp);
return 's';
} }
if (!rb_feature_p(RSTRING(fname)->ptr, Qfalse))
load_failed(fname);
return Qfalse;
} }
static void static void
@ -6031,85 +6031,101 @@ load_failed(fname)
rb_raise(rb_eLoadError, "No such file to load -- %s", RSTRING(fname)->ptr); rb_raise(rb_eLoadError, "No such file to load -- %s", RSTRING(fname)->ptr);
} }
static VALUE VALUE
load_dyna(feature, fname) rb_require_safe(fname, safe)
VALUE feature, fname; VALUE fname;
int safe;
{ {
VALUE result = Qnil;
int state; int state;
volatile int safe = ruby_safe_level; struct {
NODE *node;
ID func;
int vmode, safe;
} volatile saved;
char *volatile ftptr = 0;
if (rb_feature_p(RSTRING(feature)->ptr, Qfalse)) if (OBJ_TAINTED(fname)) {
return Qfalse; rb_check_safe_obj(fname);
rb_provide_feature(feature); }
{ StringValue(fname);
volatile int old_vmode = scope_vmode; saved.vmode = scope_vmode;
NODE *const volatile old_node = ruby_current_node; saved.node = ruby_current_node;
const volatile ID old_func = ruby_frame->last_func; saved.func = ruby_frame->last_func;
saved.safe = ruby_safe_level;
ruby_safe_level = 0;
ruby_current_node = 0;
ruby_sourcefile = rb_source_filename(RSTRING(fname)->ptr);
ruby_sourceline = 0;
ruby_frame->last_func = 0;
PUSH_TAG(PROT_NONE); PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) { if ((state = EXEC_TAG()) == 0) {
void *handle; VALUE feature, path;
long handle;
int found;
SCOPE_SET(SCOPE_PUBLIC);
handle = dln_load(RSTRING(fname)->ptr);
rb_ary_push(ruby_dln_librefs, LONG2NUM((long)handle));
}
POP_TAG();
ruby_current_node = old_node;
ruby_set_current_source();
ruby_frame->last_func = old_func;
SCOPE_SET(old_vmode);
}
ruby_safe_level = safe; ruby_safe_level = safe;
if (state) JUMP_TAG(state); found = search_required(fname, &feature, &path);
ruby_errinfo = Qnil; if (found) {
ftptr = RSTRING(feature)->ptr;
return Qtrue; if (!path) {
load_wait(ftptr);
result = Qfalse;
} }
else {
static VALUE
load_rb(feature, fname)
VALUE feature, 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; ruby_safe_level = 0;
rb_provide_feature(feature); rb_provide_feature(feature);
switch (found) {
case 'r':
/* loading ruby library should be serialized. */ /* loading ruby library should be serialized. */
if (!loading_tbl) { if (!loading_tbl) {
loading_tbl = st_init_strtable(); loading_tbl = st_init_strtable();
} }
/* partial state */ /* partial state */
ftptr = ruby_strdup(RSTRING(feature)->ptr); st_insert(loading_tbl,
st_insert(loading_tbl, (st_data_t)ftptr, (st_data_t)curr_thread); (st_data_t)(ftptr = ruby_strdup(ftptr)),
(st_data_t)curr_thread);
if (feature == fname && !OBJ_FROZEN(feature)) {
feature = rb_str_dup(feature);
OBJ_FREEZE(feature);
}
rb_load(path, 0);
break;
PUSH_TAG(PROT_NONE); case 's':
if ((state = EXEC_TAG()) == 0) { ruby_current_node = 0;
rb_load(fname, 0); ruby_sourcefile = rb_source_filename(RSTRING(path)->ptr);
ruby_sourceline = 0;
ruby_frame->last_func = 0;
SCOPE_SET(SCOPE_PUBLIC);
handle = (long)dln_load(RSTRING(path)->ptr);
rb_ary_push(ruby_dln_librefs, LONG2NUM(handle));
break;
}
result = Qtrue;
}
}
} }
POP_TAG(); POP_TAG();
st_delete(loading_tbl, (st_data_t *)&ftptr, 0); /* loading done */ ruby_current_node = saved.node;
ruby_set_current_source();
ruby_frame->last_func = saved.func;
SCOPE_SET(saved.vmode);
ruby_safe_level = saved.safe;
if (ftptr) {
if (st_delete(loading_tbl, (st_data_t *)&ftptr, 0)) { /* loading done */
free(ftptr); free(ftptr);
ruby_safe_level = safe; }
}
if (state) JUMP_TAG(state); if (state) JUMP_TAG(state);
if (NIL_P(result)) {
load_failed(fname);
}
ruby_errinfo = Qnil;
return Qtrue; return result;
} }
VALUE VALUE
rb_require(fname) rb_require(fname)
const char *fname; const char *fname;
{ {
return rb_f_require(Qnil, rb_str_new2(fname)); return rb_require_safe(rb_str_new2(fname), ruby_safe_level);
} }
static void static void

View file

@ -176,6 +176,7 @@ NORETURN(void rb_jump_tag _((int)));
int rb_provided _((const char*)); int rb_provided _((const char*));
void rb_provide _((const char*)); void rb_provide _((const char*));
VALUE rb_f_require _((VALUE, VALUE)); VALUE rb_f_require _((VALUE, VALUE));
VALUE rb_require_safe _((VALUE, int));
void rb_obj_call_init _((VALUE, int, VALUE*)); void rb_obj_call_init _((VALUE, int, VALUE*));
VALUE rb_class_new_instance _((int, VALUE*, VALUE)); VALUE rb_class_new_instance _((int, VALUE*, VALUE));
VALUE rb_block_proc _((void)); VALUE rb_block_proc _((void));

View file

@ -4,4 +4,7 @@ rcsid = %w$Id$
Version = rcsid[2].scan(/\d+/).collect!(&method(:Integer)).freeze Version = rcsid[2].scan(/\d+/).collect!(&method(:Integer)).freeze
Release = rcsid[3].freeze Release = rcsid[3].freeze
Test::Unit::AutoRunner.run(false, File.dirname(__FILE__)) runner = Test::Unit::AutoRunner.new(true)
runner.to_run.concat(ARGV)
runner.to_run << File.dirname(__FILE__) if runner.to_run.empty?
runner.run

View file

@ -1147,7 +1147,7 @@ rb_autoload(mod, id, file)
ID id; ID id;
const char *file; const char *file;
{ {
VALUE av; VALUE av, fn;
struct st_table *tbl; struct st_table *tbl;
if (!rb_is_const_id(id)) { if (!rb_is_const_id(id)) {
@ -1170,21 +1170,25 @@ rb_autoload(mod, id, file)
st_add_direct(tbl, autoload, av); st_add_direct(tbl, autoload, av);
DATA_PTR(av) = tbl = st_init_numtable(); 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, (st_data_t)rb_node_newnode(NODE_MEMO, fn, ruby_safe_level, 0));
} }
static VALUE static NODE*
autoload_delete(mod, id) autoload_delete(mod, id)
VALUE mod; VALUE mod;
ID id; ID id;
{ {
VALUE val, file = Qnil; VALUE val;
st_data_t load = 0;
st_delete(RCLASS(mod)->iv_tbl, (st_data_t*)&id, 0); st_delete(RCLASS(mod)->iv_tbl, (st_data_t*)&id, 0);
if (st_lookup(RCLASS(mod)->iv_tbl, autoload, &val)) { if (st_lookup(RCLASS(mod)->iv_tbl, autoload, &val)) {
struct st_table *tbl = check_autoload_table(val); struct st_table *tbl = check_autoload_table(val);
if (!st_delete(tbl, (st_data_t*)&id, &file)) file = Qnil; st_delete(tbl, (st_data_t*)&id, &load);
if (tbl->num_entries == 0) { if (tbl->num_entries == 0) {
DATA_PTR(val) = 0; DATA_PTR(val) = 0;
@ -1196,7 +1200,7 @@ autoload_delete(mod, id)
} }
} }
return file; return (NODE *)load;
} }
void void
@ -1205,13 +1209,12 @@ rb_autoload_load(klass, id)
ID id; ID id;
{ {
VALUE file; VALUE file;
NODE *load = autoload_delete(klass, id);
file = autoload_delete(klass, id); if (!load || !(file = load->nd_lit) || rb_provided(RSTRING(file)->ptr)) {
if (NIL_P(file) || rb_provided(RSTRING(file)->ptr)) {
const_missing(klass, id); const_missing(klass, id);
} }
FL_UNSET(file, FL_TAINT); rb_require_safe(file, load->nd_nth);
rb_f_require(Qnil, file);
} }
static VALUE static VALUE
@ -1221,11 +1224,13 @@ autoload_file(mod, id)
{ {
VALUE val, file; VALUE val, file;
struct st_table *tbl; struct st_table *tbl;
st_data_t load;
if (!st_lookup(RCLASS(mod)->iv_tbl, autoload, &val) || 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, &load)) {
return Qnil; return Qnil;
} }
file = ((NODE *)load)->nd_lit;
Check_Type(file, T_STRING); Check_Type(file, T_STRING);
if (!RSTRING(file)->ptr) { if (!RSTRING(file)->ptr) {
rb_raise(rb_eArgError, "empty file name"); rb_raise(rb_eArgError, "empty file name");