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:
parent
1b8c124c8d
commit
4de0bb549b
5 changed files with 203 additions and 162 deletions
18
ChangeLog
18
ChangeLog
|
@ -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>
|
||||
|
||||
* string.c (str_new4): should not preserve FL_TAINT status in the
|
||||
|
@ -35,7 +51,7 @@ Sat Oct 11 16:08:41 2003 Tanaka Akira <akr@m17n.org>
|
|||
Sat Oct 11 10:19:39 2003 Shugo Maeda <shugo@ruby-lang.org>
|
||||
|
||||
* lib/monitor.rb: handle exceptions correctly. Thanks, Gennady
|
||||
Bystritsky.
|
||||
Bystritsky.
|
||||
|
||||
Fri Oct 10 07:50:54 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
|
|
314
eval.c
314
eval.c
|
@ -5739,6 +5739,8 @@ rb_mod_module_eval(argc, argv, mod)
|
|||
|
||||
VALUE rb_load_path;
|
||||
|
||||
NORETURN(static void load_failed _((VALUE)));
|
||||
|
||||
void
|
||||
rb_load(fname, wrap)
|
||||
VALUE fname;
|
||||
|
@ -5761,7 +5763,7 @@ rb_load(fname, wrap)
|
|||
}
|
||||
tmp = rb_find_file(fname);
|
||||
if (!tmp) {
|
||||
rb_raise(rb_eLoadError, "No such file to load -- %s", RSTRING(fname)->ptr);
|
||||
load_failed(fname);
|
||||
}
|
||||
fname = tmp;
|
||||
|
||||
|
@ -5871,49 +5873,47 @@ VALUE ruby_dln_librefs;
|
|||
static VALUE rb_features;
|
||||
static st_table *loading_tbl;
|
||||
|
||||
static int
|
||||
rb_feature_p(feature, wait)
|
||||
const char *feature;
|
||||
int wait;
|
||||
#define IS_SOEXT(e) (strcmp(e, ".so") == 0 || strcmp(e, ".o") == 0)
|
||||
#ifdef DLEXT2
|
||||
#define IS_DLEXT(e) (strcmp(e, DLEXT) == 0 || strcmp(e, DLEXT2) == 0)
|
||||
#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;
|
||||
char *f;
|
||||
long i, len = strlen(feature);
|
||||
char *f, *e;
|
||||
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) {
|
||||
v = RARRAY(rb_features)->ptr[i];
|
||||
f = StringValuePtr(v);
|
||||
if (strcmp(f, feature) == 0) {
|
||||
goto load_wait;
|
||||
if (strncmp(f, feature, len) != 0) continue;
|
||||
if (!*(e = f + len)) {
|
||||
if (ext) continue;
|
||||
return e;
|
||||
}
|
||||
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;
|
||||
return Qtrue;
|
||||
}
|
||||
if (*e != '.') continue;
|
||||
if ((!rb || !ext) && (IS_SOEXT(e) || IS_DLEXT(e))) {
|
||||
return e;
|
||||
}
|
||||
if ((rb || !ext) && (strcmp(e, ".rb") == 0)) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *const loadable_ext[] = {
|
||||
|
@ -5928,14 +5928,7 @@ int
|
|||
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, 0, Qfalse) ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -5952,76 +5945,83 @@ rb_provide(feature)
|
|||
rb_provide_feature(rb_str_new2(feature));
|
||||
}
|
||||
|
||||
NORETURN(static void load_failed _((VALUE)));
|
||||
static VALUE load_dyna _((VALUE, VALUE));
|
||||
static VALUE load_rb _((VALUE, VALUE));
|
||||
static void
|
||||
load_wait(ftptr)
|
||||
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
|
||||
rb_f_require(obj, fname)
|
||||
VALUE obj, fname;
|
||||
{
|
||||
VALUE feature, tmp;
|
||||
char *ext; /* OK */
|
||||
return rb_require_safe(fname, ruby_safe_level);
|
||||
}
|
||||
|
||||
if (OBJ_TAINTED(fname)) {
|
||||
rb_check_safe_obj(fname);
|
||||
}
|
||||
StringValue(fname);
|
||||
ext = strrchr(RSTRING(fname)->ptr, '.');
|
||||
if (ext && strchr(ext, '/')) ext = 0;
|
||||
if (ext) {
|
||||
static int
|
||||
search_required(fname, featurep, path)
|
||||
VALUE fname, *featurep, *path;
|
||||
{
|
||||
VALUE tmp;
|
||||
char *ext, *ftptr;
|
||||
|
||||
*featurep = fname;
|
||||
*path = 0;
|
||||
ext = strrchr(ftptr = RSTRING(fname)->ptr, '.');
|
||||
if (ext && !strchr(ext, '/')) {
|
||||
if (strcmp(".rb", ext) == 0) {
|
||||
feature = rb_str_dup(fname);
|
||||
tmp = rb_find_file(fname);
|
||||
if (tmp) {
|
||||
return load_rb(feature, tmp);
|
||||
}
|
||||
load_failed(fname);
|
||||
if (rb_feature_p(ftptr, ext, Qtrue)) return 'r';
|
||||
if (*path = rb_find_file(fname)) return 'r';
|
||||
return 0;
|
||||
}
|
||||
else if (strcmp(".so", ext) == 0 || strcmp(".o", ext) == 0) {
|
||||
else if (IS_SOEXT(ext)) {
|
||||
if (rb_feature_p(ftptr, ext, Qfalse)) return 's';
|
||||
tmp = rb_str_new(RSTRING(fname)->ptr, ext-RSTRING(fname)->ptr);
|
||||
*featurep = tmp;
|
||||
#ifdef DLEXT2
|
||||
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
|
||||
feature = tmp;
|
||||
rb_str_cat2(tmp, DLEXT);
|
||||
tmp = rb_find_file(tmp);
|
||||
if (tmp) {
|
||||
return load_dyna(feature, tmp);
|
||||
if (*path = rb_find_file(tmp)) {
|
||||
return 's';
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (strcmp(DLEXT, ext) == 0) {
|
||||
tmp = rb_find_file(fname);
|
||||
if (tmp) {
|
||||
return load_dyna(fname, tmp);
|
||||
}
|
||||
else if (IS_DLEXT(ext)) {
|
||||
if (rb_feature_p(ftptr, ext, Qfalse)) return 's';
|
||||
if (*path = rb_find_file(fname)) return 's';
|
||||
}
|
||||
#ifdef DLEXT2
|
||||
else if (strcmp(DLEXT2, ext) == 0) {
|
||||
tmp = rb_find_file(fname);
|
||||
if (tmp) {
|
||||
return load_dyna(fname, tmp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if ((ext = rb_feature_p(ftptr, 0, Qfalse)) != 0) {
|
||||
return strcmp(ext, ".rb") == 0 ? 'r' : 's';
|
||||
}
|
||||
tmp = fname;
|
||||
switch (rb_find_file_ext(&tmp, loadable_ext)) {
|
||||
case 0:
|
||||
break;
|
||||
return 0;
|
||||
|
||||
case 1:
|
||||
return load_rb(tmp, tmp);
|
||||
*featurep = tmp;
|
||||
*path = rb_find_file(tmp);
|
||||
return 'r';
|
||||
|
||||
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
|
||||
|
@ -6031,85 +6031,101 @@ load_failed(fname)
|
|||
rb_raise(rb_eLoadError, "No such file to load -- %s", RSTRING(fname)->ptr);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
load_dyna(feature, fname)
|
||||
VALUE feature, fname;
|
||||
VALUE
|
||||
rb_require_safe(fname, safe)
|
||||
VALUE fname;
|
||||
int safe;
|
||||
{
|
||||
VALUE result = Qnil;
|
||||
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))
|
||||
return Qfalse;
|
||||
rb_provide_feature(feature);
|
||||
{
|
||||
volatile int old_vmode = scope_vmode;
|
||||
NODE *const volatile old_node = ruby_current_node;
|
||||
const volatile ID old_func = ruby_frame->last_func;
|
||||
|
||||
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);
|
||||
if ((state = EXEC_TAG()) == 0) {
|
||||
void *handle;
|
||||
|
||||
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);
|
||||
if (OBJ_TAINTED(fname)) {
|
||||
rb_check_safe_obj(fname);
|
||||
}
|
||||
ruby_safe_level = safe;
|
||||
if (state) JUMP_TAG(state);
|
||||
ruby_errinfo = Qnil;
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
|
||||
StringValue(fname);
|
||||
saved.vmode = scope_vmode;
|
||||
saved.node = ruby_current_node;
|
||||
saved.func = ruby_frame->last_func;
|
||||
saved.safe = ruby_safe_level;
|
||||
PUSH_TAG(PROT_NONE);
|
||||
if ((state = EXEC_TAG()) == 0) {
|
||||
rb_load(fname, 0);
|
||||
VALUE feature, path;
|
||||
long handle;
|
||||
int found;
|
||||
|
||||
ruby_safe_level = safe;
|
||||
found = search_required(fname, &feature, &path);
|
||||
if (found) {
|
||||
ftptr = RSTRING(feature)->ptr;
|
||||
if (!path) {
|
||||
load_wait(ftptr);
|
||||
result = Qfalse;
|
||||
}
|
||||
else {
|
||||
ruby_safe_level = 0;
|
||||
rb_provide_feature(feature);
|
||||
switch (found) {
|
||||
case 'r':
|
||||
/* loading ruby library should be serialized. */
|
||||
if (!loading_tbl) {
|
||||
loading_tbl = st_init_strtable();
|
||||
}
|
||||
/* partial state */
|
||||
st_insert(loading_tbl,
|
||||
(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;
|
||||
|
||||
case 's':
|
||||
ruby_current_node = 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();
|
||||
st_delete(loading_tbl, (st_data_t *)&ftptr, 0); /* loading done */
|
||||
free(ftptr);
|
||||
ruby_safe_level = safe;
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (state) JUMP_TAG(state);
|
||||
if (NIL_P(result)) {
|
||||
load_failed(fname);
|
||||
}
|
||||
ruby_errinfo = Qnil;
|
||||
|
||||
return Qtrue;
|
||||
return result;
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_require(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
|
||||
|
|
1
intern.h
1
intern.h
|
@ -176,6 +176,7 @@ NORETURN(void rb_jump_tag _((int)));
|
|||
int rb_provided _((const char*));
|
||||
void rb_provide _((const char*));
|
||||
VALUE rb_f_require _((VALUE, VALUE));
|
||||
VALUE rb_require_safe _((VALUE, int));
|
||||
void rb_obj_call_init _((VALUE, int, VALUE*));
|
||||
VALUE rb_class_new_instance _((int, VALUE*, VALUE));
|
||||
VALUE rb_block_proc _((void));
|
||||
|
|
|
@ -4,4 +4,7 @@ rcsid = %w$Id$
|
|||
Version = rcsid[2].scan(/\d+/).collect!(&method(:Integer)).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
|
||||
|
|
27
variable.c
27
variable.c
|
@ -1147,7 +1147,7 @@ rb_autoload(mod, id, file)
|
|||
ID id;
|
||||
const char *file;
|
||||
{
|
||||
VALUE av;
|
||||
VALUE av, fn;
|
||||
struct st_table *tbl;
|
||||
|
||||
if (!rb_is_const_id(id)) {
|
||||
|
@ -1170,21 +1170,25 @@ rb_autoload(mod, id, file)
|
|||
st_add_direct(tbl, autoload, av);
|
||||
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)
|
||||
VALUE mod;
|
||||
ID id;
|
||||
{
|
||||
VALUE val, file = Qnil;
|
||||
VALUE val;
|
||||
st_data_t load = 0;
|
||||
|
||||
st_delete(RCLASS(mod)->iv_tbl, (st_data_t*)&id, 0);
|
||||
if (st_lookup(RCLASS(mod)->iv_tbl, autoload, &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) {
|
||||
DATA_PTR(val) = 0;
|
||||
|
@ -1196,7 +1200,7 @@ autoload_delete(mod, id)
|
|||
}
|
||||
}
|
||||
|
||||
return file;
|
||||
return (NODE *)load;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1205,13 +1209,12 @@ rb_autoload_load(klass, id)
|
|||
ID id;
|
||||
{
|
||||
VALUE file;
|
||||
NODE *load = autoload_delete(klass, id);
|
||||
|
||||
file = autoload_delete(klass, id);
|
||||
if (NIL_P(file) || rb_provided(RSTRING(file)->ptr)) {
|
||||
if (!load || !(file = load->nd_lit) || rb_provided(RSTRING(file)->ptr)) {
|
||||
const_missing(klass, id);
|
||||
}
|
||||
FL_UNSET(file, FL_TAINT);
|
||||
rb_f_require(Qnil, file);
|
||||
rb_require_safe(file, load->nd_nth);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
@ -1221,11 +1224,13 @@ autoload_file(mod, id)
|
|||
{
|
||||
VALUE val, file;
|
||||
struct st_table *tbl;
|
||||
st_data_t load;
|
||||
|
||||
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;
|
||||
}
|
||||
file = ((NODE *)load)->nd_lit;
|
||||
Check_Type(file, T_STRING);
|
||||
if (!RSTRING(file)->ptr) {
|
||||
rb_raise(rb_eArgError, "empty file name");
|
||||
|
|
Loading…
Reference in a new issue