From 9d228b13deccfdf23f44e2c465f723a2a7b3bcbd Mon Sep 17 00:00:00 2001 From: matz Date: Tue, 14 Dec 1999 06:50:43 +0000 Subject: 19991214 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@587 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 52 ++++++ README | 2 +- README.jp | 2 +- array.c | 5 +- class.c | 27 ++- configure | 4 +- configure.in | 4 +- dir.c | 4 +- error.c | 3 + eval.c | 477 +++++++++++++++++++++++++++++----------------------- ext/dbm/dbm.c | 7 - ext/gdbm/gdbm.c | 15 +- ext/socket/socket.c | 17 +- ext/tk/lib/tk.rb | 6 +- file.c | 21 ++- gc.c | 30 +++- hash.c | 5 +- intern.h | 23 +-- io.c | 20 ++- misc/ruby-mode.el | 7 +- object.c | 29 ++-- parse.y | 38 ++--- process.c | 7 +- range.c | 14 +- re.c | 26 +++ re.h | 1 + regex.c | 61 ++++--- regex.h | 3 + ruby.h | 15 +- string.c | 17 +- struct.c | 14 +- variable.c | 171 ++++++------------- version.h | 4 +- win32/config.status | 2 +- 34 files changed, 637 insertions(+), 496 deletions(-) diff --git a/ChangeLog b/ChangeLog index 370b3588d0..1df3c184a1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,55 @@ +Mon Dec 13 15:15:31 1999 Yukihiro Matsumoto + + * regex.c (re_adjust_startpos): separate startpos adjustment + because of major performace drawback. + + * class.c (rb_singleton_class): tainted status of the singleton + class must synchronize with the object. + + * eval.c (rb_thread_schedule): implement thread priority. + +Sat Dec 11 03:34:38 1999 Yukihiro Matsumoto + + * gc.c (mark_hashentry): key should be VALUE, not ID. + + * io.c (argf_eof): should check next_p too. + +Thu Dec 9 18:09:13 1999 EGUCHI Osamu + + * error.c (exc_set_backtrace): forgot to declare a VALUE argument. + +Thu Dec 9 14:19:31 1999 Yukihiro Matsumoto + + * object.c (rb_obj_taint): explicit tainting must be prohibited at + level 4 to prevent polluting trusted object by untrusted code. + + * file.c: file operations (stat, lstat, chmod, chown, umask, + truncate, flock) are prohibited in level 2 (was level 4). + +Wed Dec 8 11:48:23 1999 Yukihiro Matsumoto + + * eval.c (rb_f_require): prohibiting require() in the secure mode + cause serious autoloading error. + + * variable.c (rb_obj_instance_variables): don't need to prohibit + to get list of instance variable names of untainted objects. + + * variable.c (rb_ivar_get): don't need to prohibit to get instance + variables of untainted objects. + + * variable.c (rb_mod_remove_const): should prohibit constant + removals too. + +Wed Dec 8 09:23:01 1999 Yukihiro Matsumoto + + * eval.c (rb_eval): should try autoloading before defining + class/module at the toplevel. + +Tue Dec 7 22:15:30 1999 EGUCHI Osamu + + * configure.in: Modified rb_cv_rshift_sign detect routine and + more simple/fast RSHIFT() for hpux-10.x. + Tue Dec 7 11:16:30 1999 Yukihiro Matsumoto * eval.c (Init_eval): calculate stack limit from rlimit where diff --git a/README b/README index 2953cc98da..5ed6015be0 100644 --- a/README +++ b/README @@ -135,7 +135,7 @@ You can redistribute it and/or modify it under either the terms of the GPL The URL of the Ruby home-page is: - http://www.netlab.co.jp/ruby/ + http://www.ruby-lang.org/ * The Author diff --git a/README.jp b/README.jp index 6c320c89f4..515f658609 100644 --- a/README.jp +++ b/README.jp @@ -44,7 +44,7 @@ Ruby RubyのホームページのURLは - http://www.netlab.co.jp/ruby/jp/ + http://www.ruby-lang.org/ です. diff --git a/array.c b/array.c index 2cc9a07c89..6401bc4886 100644 --- a/array.c +++ b/array.c @@ -49,7 +49,7 @@ rb_ary_modify(ary) rb_raise(rb_eTypeError, "can't modify frozen array"); if (FL_TEST(ary, ARY_TMPLOCK)) rb_raise(rb_eTypeError, "can't modify array during sort"); - if (!FL_TEST(ary, FL_TAINT) && rb_safe_level() >= 4) + if (!OBJ_TAINTED(ary) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: can't modify array"); } @@ -57,6 +57,9 @@ VALUE rb_ary_freeze(ary) VALUE ary; { + if (rb_safe_level() >= 4 && !OBJ_TAINTED(ary)) + rb_raise(rb_eSecurityError, "Insecure: can't freeze array"); + FL_SET(ary, ARY_FREEZE); return ary; } diff --git a/class.c b/class.c index 6ffd328215..46989474a8 100644 --- a/class.c +++ b/class.c @@ -130,7 +130,7 @@ rb_define_class_under(outer, name, super) id = rb_intern(name); klass = rb_define_class_id(id, super); - rb_shvar_set(outer, id, klass); + rb_const_set(outer, id, klass); rb_set_class_path(klass, outer, name); return klass; @@ -186,7 +186,7 @@ rb_define_module_under(outer, name) id = rb_intern(name); module = rb_define_module_id(id); - rb_shvar_set(outer, id, module); + rb_const_set(outer, id, module); rb_set_class_path(module, outer, name); return module; @@ -368,7 +368,7 @@ method_list(mod, option, func) VALUE klass; VALUE *p, *q, *pend; - if (!FL_TEST(mod, FL_TAINT) && rb_safe_level() >= 4) + if (!OBJ_TAINTED(mod) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: can't get metainfo"); ary = rb_ary_new(); for (klass = mod; klass; klass = RCLASS(klass)->super) { @@ -431,7 +431,7 @@ rb_obj_singleton_methods(obj) VALUE klass; VALUE *p, *q, *pend; - if (rb_safe_level() >= 4 && !FL_TEST(obj, FL_TAINT)) + if (rb_safe_level() >= 4 && !OBJ_TAINTED(obj)) rb_raise(rb_eSecurityError, "Insecure: can't get metainfo"); ary = rb_ary_new(); klass = CLASS_OF(obj); @@ -510,15 +510,26 @@ VALUE rb_singleton_class(obj) VALUE obj; { + VALUE klass; if (rb_special_const_p(obj)) { rb_raise(rb_eTypeError, "can't define singleton"); } if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON)) { - return RBASIC(obj)->klass; + klass = RBASIC(obj)->klass; + } + else { + klass = rb_singleton_class_new(RBASIC(obj)->klass); + RBASIC(obj)->klass = klass; + rb_singleton_class_attached(klass, obj); + } + if (OBJ_TAINTED(obj)) { + OBJ_TAINT(klass); } - RBASIC(obj)->klass = rb_singleton_class_new(RBASIC(obj)->klass); - rb_singleton_class_attached(RBASIC(obj)->klass, obj); - return RBASIC(obj)->klass; + else { + FL_UNSET(klass, FL_TAINT); + } + + return klass; } void diff --git a/configure b/configure index 32b89d596c..0a63be065b 100644 --- a/configure +++ b/configure @@ -3783,7 +3783,7 @@ else int main() { - if (-1==(-1>>(unsigned)1)) + if (-1==(-1>>1)) return 0; return 1; } @@ -3806,7 +3806,7 @@ fi echo "$ac_t""$rb_cv_rshift_sign" 1>&6 if test "$rb_cv_rshift_sign" = yes; then cat >> confdefs.h <<\EOF -#define RSHIFT(x,y) ((x)>>y) +#define RSHIFT(x,y) ((x)>>(int)y) EOF else diff --git a/configure.in b/configure.in index 962cfc20f5..e4ac66aeec 100644 --- a/configure.in +++ b/configure.in @@ -260,7 +260,7 @@ AC_CACHE_CHECK(whether right shift preserve sign bit, rb_cv_rshift_sign, int main() { - if (-1==(-1>>(unsigned)1)) + if (-1==(-1>>1)) return 0; return 1; } @@ -269,7 +269,7 @@ main() rb_cv_rshift_sign=no, rb_cv_rshift_sign=yes)]) if test "$rb_cv_rshift_sign" = yes; then - AC_DEFINE(RSHIFT(x,y), ((x)>>y)) + AC_DEFINE(RSHIFT(x,y), ((x)>>(int)y)) else AC_DEFINE(RSHIFT(x,y), (((x)<0) ? ~((~(x))>>y) : (x)>>y)) fi diff --git a/dir.c b/dir.c index a0a5d3eddd..3c0581c777 100644 --- a/dir.c +++ b/dir.c @@ -435,7 +435,6 @@ dir_s_mkdir(argc, argv, obj) VALUE path, vmode; int mode; - rb_secure(2); if (rb_scan_args(argc, argv, "11", &path, &vmode) == 2) { mode = NUM2INT(vmode); } @@ -444,6 +443,7 @@ dir_s_mkdir(argc, argv, obj) } Check_SafeStr(path); + rb_secure(2); #if !defined(NT) && !defined(USE_CWGUSI) if (mkdir(RSTRING(path)->ptr, mode) == -1) rb_sys_fail(RSTRING(path)->ptr); @@ -459,8 +459,8 @@ static VALUE dir_s_rmdir(obj, dir) VALUE obj, dir; { - rb_secure(2); Check_SafeStr(dir); + rb_secure(2); if (rmdir(RSTRING(dir)->ptr) < 0) rb_sys_fail(RSTRING(dir)->ptr); diff --git a/error.c b/error.c index 143a11e352..762151cc79 100644 --- a/error.c +++ b/error.c @@ -247,6 +247,7 @@ VALUE rb_eIndexError; VALUE rb_eLoadError; VALUE rb_eSecurityError; VALUE rb_eNotImpError; +VALUE rb_eNoMemError; VALUE rb_eSystemCallError; VALUE rb_mErrno; @@ -387,6 +388,7 @@ check_backtrace(bt) static VALUE exc_set_backtrace(exc, bt) VALUE exc; + VALUE bt; { return rb_iv_set(exc, "bt", check_backtrace(bt)); } @@ -541,6 +543,7 @@ Init_Exception() rb_eRuntimeError = rb_define_class("RuntimeError", rb_eStandardError); rb_eSecurityError = rb_define_class("SecurityError", rb_eStandardError); rb_eNotImpError = rb_define_class("NotImplementError", rb_eException); + rb_eNoMemError = rb_define_class("NoMemoryError", rb_eException); init_syserr(); } diff --git a/eval.c b/eval.c index e1fe0537be..0e16db765a 100644 --- a/eval.c +++ b/eval.c @@ -90,6 +90,73 @@ static int scope_vmode; #define SCOPE_SET(f) do {scope_vmode=(f);} while(0) #define SCOPE_TEST(f) (scope_vmode&(f)) +static int safe_level = 0; +/* safe-level: + 0 - strings from streams/environment/ARGV are tainted (default) + 1 - no dangerous operation by tainted string + 2 - process/file operations prohibited + 3 - all genetated strings are tainted + 4 - no global (non-tainted) variable modification/no direct output +*/ + +int +rb_safe_level() +{ + return safe_level; +} + +void +rb_set_safe_level(level) + int level; +{ + if (level > safe_level) { + safe_level = level; + } +} + +static VALUE +safe_getter() +{ + return INT2FIX(safe_level); +} + +static void +safe_setter(val) + VALUE val; +{ + int level = NUM2INT(val); + + if (level < safe_level) { + rb_raise(rb_eSecurityError, "tried to downgrade safe level from %d to %d", + safe_level, level); + } + safe_level = level; +} + +void +rb_check_safe_str(x) + VALUE x; +{ + if (safe_level > 0 && OBJ_TAINTED(x)){ + rb_raise(rb_eSecurityError, "Insecure operation - %s", + rb_id2name(ruby_frame->last_func)); + } + if (TYPE(x)!= T_STRING) { + rb_raise(rb_eTypeError, "wrong argument type %s (expected String)", + rb_class2name(CLASS_OF(x))); + } +} + +void +rb_secure(level) + int level; +{ + if (level <= safe_level) { + rb_raise(rb_eSecurityError, "Insecure operation `%s' for level %d", + rb_id2name(ruby_frame->last_func), safe_level); + } +} + static void print_undef _((VALUE, ID)) NORETURN; static void print_undef(klass, id) @@ -158,6 +225,9 @@ rb_add_method(klass, mid, node, noex) if (klass == rb_cObject) { rb_secure(4); } + if (safe_level >= 4 && !OBJ_TAINTED(klass)) { + rb_raise(rb_eSecurityError, "Insecure: can't define method"); + } body = NEW_METHOD(node, noex); st_insert(RCLASS(klass)->m_tbl, mid, body); } @@ -225,38 +295,6 @@ rb_get_method_body(klassp, idp, noexp) return body; } -void -rb_alias(klass, name, def) - VALUE klass; - ID name, def; -{ - VALUE origin; - NODE *orig, *body; - - if (name == def) return; - if (klass == rb_cObject) { - rb_secure(4); - } - orig = search_method(klass, def, &origin); - if (!orig || !orig->nd_body) { - if (TYPE(klass) == T_MODULE) { - orig = search_method(rb_cObject, def, &origin); - } - } - if (!orig || !orig->nd_body) { - print_undef(klass, def); - } - body = orig->nd_body; - if (nd_type(body) == NODE_FBODY) { /* was alias */ - def = body->nd_mid; - origin = body->nd_orig; - body = body->nd_head; - } - - st_insert(RCLASS(klass)->m_tbl, name, - NEW_METHOD(NEW_FBODY(body, def, origin), orig->nd_noex)); -} - static void remove_method(klass, mid) VALUE klass; @@ -267,6 +305,9 @@ remove_method(klass, mid) if (klass == rb_cObject) { rb_secure(4); } + if (safe_level >= 4 && !OBJ_TAINTED(klass)) { + rb_raise(rb_eSecurityError, "Insecure: can't remove method"); + } if (!st_delete(RCLASS(klass)->m_tbl, &mid, &body)) { rb_raise(rb_eNameError, "method `%s' not defined in %s", rb_id2name(mid), rb_class2name(klass)); @@ -282,6 +323,14 @@ rb_remove_method(klass, name) remove_method(klass, rb_intern(name)); } +static VALUE +rb_mod_remove_method(mod, name) + VALUE mod, name; +{ + remove_method(mod, rb_to_id(name)); + return mod; +} + void rb_disable_super(klass, name) VALUE klass; @@ -740,75 +789,6 @@ static VALUE module_setup _((VALUE,NODE*)); static VALUE massign _((VALUE,NODE*,VALUE,int)); static void assign _((VALUE,NODE*,VALUE,int)); -static int safe_level = 0; -/* safe-level: - 0 - strings from streams/environment/ARGV are tainted (default) - 1 - no dangerous operation by tainted string - 2 - process/file operations prohibited - 3 - all genetated strings are tainted - 4 - no global (non-tainted) variable modification/no direct output -*/ - -int -rb_safe_level() -{ - return safe_level; -} - -void -rb_set_safe_level(level) - int level; -{ - if (level > safe_level) { - safe_level = level; - } -} - -static VALUE -safe_getter() -{ - return INT2FIX(safe_level); -} - -static void -safe_setter(val) - VALUE val; -{ - int level = NUM2INT(val); - - if (level < safe_level) { - rb_raise(rb_eSecurityError, "tried to downgrade safe level from %d to %d", - safe_level, level); - } - safe_level = level; -} - -void -rb_check_safe_str(x) - VALUE x; -{ - if (TYPE(x)!= T_STRING) { - rb_raise(rb_eTypeError, "wrong argument type %s (expected String)", - rb_class2name(CLASS_OF(x))); - } - if (OBJ_TAINTED(x)) { - if (safe_level > 0){ - rb_raise(rb_eSecurityError, "Insecure operation - %s", - rb_id2name(ruby_frame->last_func)); - } - } -} - -void -rb_secure(level) - int level; -{ - if (level <= safe_level) { - rb_raise(rb_eSecurityError, "Insecure operation `%s' for level %d", - rb_id2name(ruby_frame->last_func), safe_level); - } -} - static VALUE trace_func = 0; static void call_trace_func _((char*,char*,int,VALUE,ID,VALUE)); @@ -1322,7 +1302,7 @@ superclass(self, node) } static VALUE -ev_shvar_defined(cref, id) +ev_const_defined(cref, id) NODE *cref; ID id; { @@ -1337,11 +1317,11 @@ ev_shvar_defined(cref, id) } cbase = cbase->nd_next; } - return rb_shvar_defined(cref->nd_clss, id); + return rb_const_defined(cref->nd_clss, id); } static VALUE -ev_shvar_get(cref, id) +ev_const_get(cref, id) NODE *cref; ID id; { @@ -1356,11 +1336,11 @@ ev_shvar_get(cref, id) } cbase = cbase->nd_next; } - return rb_shvar_get(cref->nd_clss, id); + return rb_const_get(cref->nd_clss, id); } static VALUE -ev_shvar_set(cref, id, val) +ev_const_set(cref, id, val) NODE *cref; ID id; VALUE val; @@ -1377,7 +1357,7 @@ ev_shvar_set(cref, id, val) } cbase = cbase->nd_next; } - rb_shvar_assign(cbase->nd_clss, id, val); + rb_const_assign(cbase->nd_clss, id, val); return val; } @@ -1395,47 +1375,103 @@ rb_mod_nesting() } static VALUE -rb_mod_s_shvars() +rb_mod_s_constants() { NODE *cbase = (NODE*)ruby_frame->cbase; VALUE ary = rb_ary_new(); while (cbase && cbase->nd_clss != rb_cObject) { - rb_mod_shvar_at(cbase->nd_clss, ary); + rb_mod_const_at(cbase->nd_clss, ary); cbase = cbase->nd_next; } - rb_mod_shvar_of(((NODE*)ruby_frame->cbase)->nd_clss, ary); + rb_mod_const_of(((NODE*)ruby_frame->cbase)->nd_clss, ary); return ary; } -static VALUE -rb_mod_remove_method(mod, name) - VALUE mod, name; +void +rb_undef(klass, id) + VALUE klass; + ID id; { - remove_method(mod, rb_to_id(name)); - return mod; + VALUE origin; + NODE *body; + + if (safe_level >= 4 && !OBJ_TAINTED(klass)) { + rb_raise(rb_eSecurityError, "Insecure: can't undef"); + } + body = search_method(ruby_class, id, &origin); + if (!body || !body->nd_body) { + char *s0 = " class"; + VALUE c = klass; + + if (FL_TEST(c, FL_SINGLETON)) { + VALUE obj = rb_iv_get(klass, "__attached__"); + + switch (TYPE(obj)) { + case T_MODULE: + case T_CLASS: + c = obj; + s0 = ""; + } + } + else if (TYPE(c) == T_MODULE) { + s0 = " module"; + } + rb_raise(rb_eNameError, "undefined method `%s' for%s `%s'", + rb_id2name(id),s0,rb_class2name(c)); + } + rb_clear_cache_by_id(id); + rb_add_method(klass, id, 0, NOEX_PUBLIC); + rb_clear_cache_by_id(id); } static VALUE rb_mod_undef_method(mod, name) VALUE mod, name; { - ID id = rb_to_id(name); - - rb_add_method(mod, id, 0, NOEX_PUBLIC); - rb_clear_cache_by_id(id); + rb_undef(mod, rb_to_id(name)); return mod; } +void +rb_alias(klass, name, def) + VALUE klass; + ID name, def; +{ + VALUE origin; + NODE *orig, *body; + + if (name == def) return; + if (klass == rb_cObject) { + rb_secure(4); + } + orig = search_method(klass, def, &origin); + if (!orig || !orig->nd_body) { + if (TYPE(klass) == T_MODULE) { + orig = search_method(rb_cObject, def, &origin); + } + } + if (!orig || !orig->nd_body) { + print_undef(klass, def); + } + body = orig->nd_body; + if (nd_type(body) == NODE_FBODY) { /* was alias */ + def = body->nd_mid; + origin = body->nd_orig; + body = body->nd_head; + } + + st_insert(RCLASS(klass)->m_tbl, name, + NEW_METHOD(NEW_FBODY(body, def, origin), orig->nd_noex)); + rb_clear_cache_by_id(name); +} + static VALUE rb_mod_alias_method(mod, newname, oldname) VALUE mod, newname, oldname; { - ID id = rb_to_id(newname); - - rb_alias(mod, id, rb_to_id(oldname)); - rb_clear_cache_by_id(id); + rb_alias(mod, rb_to_id(newname), rb_to_id(oldname)); return mod; } @@ -1628,7 +1664,7 @@ is_defined(self, node, buf) break; case NODE_CVAR: - if (ev_shvar_defined((NODE*)ruby_frame->cbase, node->nd_vid)) { + if (ev_const_defined((NODE*)ruby_frame->cbase, node->nd_vid)) { return "constant"; } break; @@ -1644,7 +1680,7 @@ is_defined(self, node, buf) switch (TYPE(val)) { case T_CLASS: case T_MODULE: - if (rb_shvar_defined_at(val, node->nd_mid)) + if (rb_const_defined_at(val, node->nd_mid)) return "constant"; default: if (rb_method_boundp(val, node->nd_mid, 1)) { @@ -2435,7 +2471,7 @@ rb_eval(self, node) rb_raise(rb_eTypeError, "no class/module to define constant"); } result = rb_eval(self, node->nd_value); - ev_shvar_set((NODE*)ruby_frame->cbase, node->nd_vid, result); + ev_const_set((NODE*)ruby_frame->cbase, node->nd_vid, result); break; case NODE_CDECL: @@ -2443,7 +2479,7 @@ rb_eval(self, node) rb_raise(rb_eTypeError, "no class/module to define constant"); } result = rb_eval(self, node->nd_value); - rb_shvar_set(ruby_class, node->nd_vid, result); + rb_const_set(ruby_class, node->nd_vid, result); break; case NODE_LVAR: @@ -2466,7 +2502,7 @@ rb_eval(self, node) break; case NODE_CVAR: - result = ev_shvar_get((NODE*)ruby_frame->cbase, node->nd_vid); + result = ev_const_get((NODE*)ruby_frame->cbase, node->nd_vid); break; case NODE_BLOCK_ARG: @@ -2493,12 +2529,12 @@ rb_eval(self, node) default: return rb_funcall(klass, node->nd_mid, 0, 0); } - result = rb_shvar_get(klass, node->nd_mid); + result = rb_const_get(klass, node->nd_mid); } break; case NODE_COLON3: - result = rb_shvar_get(rb_cObject, node->nd_mid); + result = rb_const_get(rb_cObject, node->nd_mid); break; case NODE_NTH_REF: @@ -2654,14 +2690,9 @@ rb_eval(self, node) rb_warn("re-defining Object#initialize may cause infinite loop"); } body = search_method(ruby_class, node->nd_mid, &origin); - if (body) { - if (origin == ruby_class) { - if (safe_level >= 4) { - rb_raise(rb_eSecurityError, "re-defining method prohibited"); - } - if (RTEST(ruby_verbose)) { - rb_warning("discarding old %s", rb_id2name(node->nd_mid)); - } + if (body){ + if (RTEST(ruby_verbose)) { + rb_warning("discarding old %s", rb_id2name(node->nd_mid)); } rb_clear_cache_by_id(node->nd_mid); } @@ -2711,7 +2742,7 @@ rb_eval(self, node) rb_class2name(CLASS_OF(recv))); } - if (rb_safe_level() >= 4 && !FL_TEST(recv, FL_TAINT)) { + if (safe_level >= 4 && !OBJ_TAINTED(recv)) { rb_raise(rb_eSecurityError, "can't define singleton method"); } klass = rb_singleton_class(recv); @@ -2733,40 +2764,14 @@ rb_eval(self, node) break; case NODE_UNDEF: - { - VALUE origin; - NODE *body; - - if (NIL_P(ruby_class)) { - rb_raise(rb_eTypeError, "no class to undef method"); - } - if (ruby_class == rb_cObject) { - rb_secure(4); - } - body = search_method(ruby_class, node->nd_mid, &origin); - if (!body || !body->nd_body) { - char *s0 = " class"; - VALUE klass = ruby_class; - - if (FL_TEST(ruby_class, FL_SINGLETON)) { - VALUE obj = rb_iv_get(ruby_class, "__attached__"); - switch (TYPE(obj)) { - case T_MODULE: - case T_CLASS: - klass = obj; - s0 = ""; - } - } - else if (TYPE(klass) == T_MODULE) { - s0 = " module"; - } - rb_raise(rb_eNameError, "undefined method `%s' for%s `%s'", - rb_id2name(node->nd_mid),s0,rb_class2name(klass)); - } - rb_clear_cache_by_id(node->nd_mid); - rb_add_method(ruby_class, node->nd_mid, 0, NOEX_PUBLIC); - result = Qnil; + if (NIL_P(ruby_class)) { + rb_raise(rb_eTypeError, "no class to undef method"); + } + if (ruby_class == rb_cObject) { + rb_secure(4); } + rb_undef(ruby_class, node->nd_mid); + result = Qnil; break; case NODE_ALIAS: @@ -2799,12 +2804,16 @@ rb_eval(self, node) } klass = 0; - if (rb_shvar_defined_at(ruby_class, node->nd_cname) && - (ruby_class != rb_cObject || !rb_autoload_defined(node->nd_cname))) { - klass = rb_shvar_get(ruby_class, node->nd_cname); + if ((ruby_class == rb_cObject || ruby_class == ruby_wrapper) && + rb_autoload_defined(node->nd_cname)) { + rb_autoload_load(node->nd_cname); + } + if (rb_const_defined_at(ruby_class, node->nd_cname)) { + klass = rb_const_get(ruby_class, node->nd_cname); } - if (ruby_wrapper && rb_shvar_defined_at(rb_cObject, node->nd_cname)) { - klass = rb_shvar_get(rb_cObject, node->nd_cname); + if (!klass && ruby_class == ruby_wrapper && + rb_const_defined_at(rb_cObject, node->nd_cname)) { + klass = rb_const_get(rb_cObject, node->nd_cname); } if (klass) { if (TYPE(klass) != T_CLASS) { @@ -2832,7 +2841,7 @@ rb_eval(self, node) else { if (!super) super = rb_cObject; klass = rb_define_class_id(node->nd_cname, super); - rb_shvar_set(ruby_class, node->nd_cname, klass); + rb_const_set(ruby_class, node->nd_cname, klass); rb_set_class_path(klass,ruby_class,rb_id2name(node->nd_cname)); } if (ruby_wrapper) { @@ -2852,13 +2861,16 @@ rb_eval(self, node) rb_raise(rb_eTypeError, "no outer class/module"); } module = 0; - if (rb_shvar_defined_at(ruby_class, node->nd_cname) && - (ruby_class != rb_cObject || - !rb_autoload_defined(node->nd_cname))) { - module = rb_shvar_get(ruby_class, node->nd_cname); + if ((ruby_class == rb_cObject || ruby_class == ruby_wrapper) && + rb_autoload_defined(node->nd_cname)) { + rb_autoload_load(node->nd_cname); } - if (ruby_wrapper && rb_shvar_defined_at(rb_cObject, node->nd_cname)) { - module = rb_shvar_get(rb_cObject, node->nd_cname); + if (rb_const_defined_at(ruby_class, node->nd_cname)) { + module = rb_const_get(ruby_class, node->nd_cname); + } + if (!module && ruby_class == ruby_wrapper && + rb_const_defined_at(rb_cObject, node->nd_cname)) { + module = rb_const_get(rb_cObject, node->nd_cname); } if (module) { if (TYPE(module) != T_MODULE) { @@ -2871,7 +2883,7 @@ rb_eval(self, node) } else { module = rb_define_module_id(node->nd_cname); - rb_shvar_set(ruby_class, node->nd_cname, module); + rb_const_set(ruby_class, node->nd_cname, module); rb_set_class_path(module,ruby_class,rb_id2name(node->nd_cname)); } if (ruby_wrapper) { @@ -2892,10 +2904,13 @@ rb_eval(self, node) rb_raise(rb_eTypeError, "no virtual class for %s", rb_class2name(CLASS_OF(klass))); } + if (safe_level >= 4 && !OBJ_TAINTED(klass)) + rb_raise(rb_eSecurityError, "Insecure: can't extend object"); if (FL_TEST(CLASS_OF(klass), FL_SINGLETON)) { rb_clear_cache(); } klass = rb_singleton_class(klass); + if (ruby_wrapper) { rb_extend_object(klass, ruby_wrapper); rb_include_module(klass, ruby_wrapper); @@ -3414,11 +3429,11 @@ assign(self, lhs, val, check) break; case NODE_CASGN: - ev_shvar_set((NODE*)ruby_frame->cbase, lhs->nd_vid, val); + ev_const_set((NODE*)ruby_frame->cbase, lhs->nd_vid, val); break; case NODE_CDECL: - rb_shvar_set(ruby_class, lhs->nd_vid, val); + rb_const_set(ruby_class, lhs->nd_vid, val); break; case NODE_MASGN: @@ -4557,7 +4572,7 @@ static VALUE yield_under(under, self) VALUE under, self; { - if (rb_safe_level() >= 4 && !FL_TEST(self, FL_TAINT)) + if (safe_level >= 4 && !OBJ_TAINTED(self)) rb_raise(rb_eSecurityError, "Insecure: can't eval"); return exec_under(yield_under_i, under, self); } @@ -4649,7 +4664,6 @@ static char* find_file(file) char *file; { - extern VALUE rb_load_path; volatile VALUE vpath; char *path; @@ -4692,7 +4706,7 @@ find_file(file) vpath = rb_ary_join(vpath, rb_str_new2(PATH_SEP)); path = STR2CSTR(vpath); if (safe_level >= 2 && !rb_path_check(path)) { - rb_raise(rb_eSecurityError, "loading from unsefe path %s", path); + rb_raise(rb_eSecurityError, "loading from unsafe path %s", path); } } else { @@ -4868,8 +4882,8 @@ rb_f_require(obj, fname) char *ext, *file, *feature, *buf; /* OK */ volatile VALUE load; int state; + volatile int safe = safe_level; - rb_secure(4); Check_SafeStr(fname); if (rb_provided(RSTRING(fname)->ptr)) return Qfalse; @@ -4936,6 +4950,7 @@ rb_f_require(obj, fname) return Qtrue; load_rb: + safe_level = 0; if (rb_thread_loading(feature)) return Qfalse; rb_provide(feature); @@ -4945,6 +4960,7 @@ rb_f_require(obj, fname) } POP_TAG(); rb_thread_loading_done(feature); + safe_level = safe; if (state) JUMP_TAG(state); return Qtrue; @@ -5399,9 +5415,7 @@ Init_eval() rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2); rb_define_singleton_method(rb_cModule, "nesting", rb_mod_nesting, 0); - rb_define_singleton_method(rb_cModule, "shared_variables", rb_mod_s_shvars, 0); - /* to be removed at 1.6 */ - rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_shvars, 0); + rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, 0); rb_define_singleton_method(ruby_top_self, "include", top_include, -1); rb_define_singleton_method(ruby_top_self, "public", top_public, -1); @@ -5617,7 +5631,7 @@ static void proc_save_safe_level(data) VALUE data; { - if (FL_TEST(data, FL_TAINT)) { + if (OBJ_TAINTED(data)) { switch (safe_level) { case 3: FL_SET(data, PROC_T3); @@ -5636,7 +5650,7 @@ static void proc_set_safe_level(data) VALUE data; { - if (FL_TEST(data, FL_TAINT)) { + if (OBJ_TAINTED(data)) { switch (RBASIC(data)->flags & PROC_TMASK) { case PROC_T3: safe_level = 3; @@ -5923,8 +5937,8 @@ rb_obj_method(obj, vid) data->body = body; data->oklass = CLASS_OF(obj); data->oid = rb_to_id(vid); - if (FL_TEST(obj, FL_TAINT)) { - FL_SET(method, FL_TAINT); + if (OBJ_TAINTED(obj)) { + OBJ_TAINT(method); } return method; @@ -5944,8 +5958,8 @@ method_call(argc, argv, method) Data_Get_Struct(method, struct METHOD, data); PUSH_ITER(rb_iterator_p()?ITER_PRE:ITER_NOT); PUSH_TAG(PROT_NONE); - if (FL_TEST(data->recv, FL_TAINT) || FL_TEST(method, FL_TAINT)) { - FL_SET(method, FL_TAINT); + if (OBJ_TAINTED(data->recv) || OBJ_TAINTED(method)) { + OBJ_TAINT(method); if (safe_level < 4) safe_level = 4; } if ((state = EXEC_TAG()) == 0) { @@ -6140,6 +6154,7 @@ struct thread { thread_t join; int abort; + int priority; st_table *locals; @@ -6270,8 +6285,8 @@ rb_thread_save_context(th) th->stk_len = 0; th->stk_pos = (rb_gc_stack_start<(VALUE*)&v)?rb_gc_stack_start :rb_gc_stack_start - len; - if (len > th->stk_max) { - REALLOC_N(th->stk_ptr, VALUE, len); + if (len > th->stk_max) { +REALLOC_N(th->stk_ptr, VALUE, len); th->stk_max = len; } th->stk_len = len; @@ -6501,8 +6516,8 @@ rb_thread_schedule() FOREACH_THREAD_FROM(curr, th) { if (th->status != THREAD_STOPPED && th->status != THREAD_KILLED) { - next = th; - break; + if (!next || next->priority < th->priority) + next = th; } } END_FOREACH_FROM(curr, th); @@ -6514,7 +6529,8 @@ rb_thread_schedule() th->wait_for &= ~WAIT_JOIN; th->status = THREAD_RUNNABLE; num_waiting_on_join--; - if (!next) next = th; + if (!next || next->priority < th->priority) + next = th; } } END_FOREACH_FROM(curr, th); @@ -6600,7 +6616,8 @@ rb_thread_schedule() th->fd = 0; th->wait_for &= ~WAIT_FD; num_waiting_on_fd--; - if (!next) next = th; /* Found one. */ + if (!next || next->priority < th->priority) + next = th; /* Found one. */ } } END_FOREACH_FROM(curr, th); @@ -6972,6 +6989,31 @@ rb_thread_sleep_forever() rb_thread_schedule(); } +static VALUE +rb_thread_priority(thread) + VALUE thread; +{ + thread_t th = rb_thread_check(thread);; + + if (safe_level >= 4 && th != curr_thread) { + rb_raise(rb_eSecurityError, "Insecure: can't get priority"); + } + return INT2NUM(th->priority); +} + +static VALUE +rb_thread_priority_set(thread, prio) + VALUE thread, prio; +{ + thread_t th; + + rb_secure(4); + th = rb_thread_check(thread); + + th->priority = NUM2INT(prio); + return thread; +} + static int thread_abort; static VALUE @@ -6984,6 +7026,7 @@ static VALUE rb_thread_s_abort_exc_set(self, val) VALUE self, val; { + rb_secure(4); thread_abort = RTEST(val); return val; } @@ -7003,6 +7046,7 @@ rb_thread_abort_exc_set(thread, val) { thread_t th = rb_thread_check(thread); + rb_secure(4); th->abort = RTEST(val); return val; } @@ -7035,6 +7079,7 @@ rb_thread_abort_exc_set(thread, val) th->last_line = 0;\ th->last_match = 0;\ th->abort = 0;\ + th->priority = 0;\ th->locals = 0;\ } while(0) @@ -7052,6 +7097,7 @@ rb_thread_alloc(klass) curr_thread->next->prev = th; th->next = curr_thread->next; curr_thread->next = th; + th->priority = curr_thread->priority; } else { curr_thread = th->prev = th->next = th; @@ -7278,13 +7324,13 @@ rb_thread_cleanup() int rb_thread_critical; static VALUE -rb_thread_get_critical() +rb_thread_critical_get() { return rb_thread_critical?Qtrue:Qfalse; } static VALUE -rb_thread_set_critical(obj, val) +rb_thread_critical_set(obj, val) VALUE obj, val; { rb_thread_critical = RTEST(val); @@ -7417,6 +7463,9 @@ rb_thread_local_aref(thread, id) VALUE val; th = rb_thread_check(thread); + if (safe_level >= 4 && th != curr_thread) { + rb_raise(rb_eSecurityError, "Insecure: thread locals"); + } if (!th->locals) return Qnil; if (st_lookup(th->locals, id, &val)) { return val; @@ -7439,8 +7488,9 @@ rb_thread_local_aset(thread, id, val) { thread_t th = rb_thread_check(thread); - if (safe_level >= 4 && !FL_TEST(thread, FL_TAINT)) - rb_raise(rb_eSecurityError, "Insecure: can't modify thread values"); + if (safe_level >= 4 && th != curr_thread) { + rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals"); + } if (!th->locals) { th->locals = st_init_numtable(); @@ -7541,8 +7591,8 @@ Init_Thread() rb_define_singleton_method(rb_cThread, "current", rb_thread_current, 0); rb_define_singleton_method(rb_cThread, "main", rb_thread_main, 0); - rb_define_singleton_method(rb_cThread, "critical", rb_thread_get_critical, 0); - rb_define_singleton_method(rb_cThread, "critical=", rb_thread_set_critical, 1); + rb_define_singleton_method(rb_cThread, "critical", rb_thread_critical_get, 0); + rb_define_singleton_method(rb_cThread, "critical=", rb_thread_critical_set, 1); rb_define_singleton_method(rb_cThread, "abort_on_exception", rb_thread_s_abort_exc, 0); rb_define_singleton_method(rb_cThread, "abort_on_exception=", rb_thread_s_abort_exc_set, 1); @@ -7560,6 +7610,9 @@ Init_Thread() rb_define_method(rb_cThread, "abort_on_exception", rb_thread_abort_exc, 0); rb_define_method(rb_cThread, "abort_on_exception=", rb_thread_abort_exc_set, 1); + rb_define_method(rb_cThread, "priority", rb_thread_priority, 0); + rb_define_method(rb_cThread, "priority=", rb_thread_priority_set, 1); + rb_define_method(rb_cThread, "[]", rb_thread_aref, 1); rb_define_method(rb_cThread, "[]=", rb_thread_aset, 2); rb_define_method(rb_cThread, "key?", rb_thread_key_p, 1); diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c index 1240f4b9ab..2aeede2672 100644 --- a/ext/dbm/dbm.c +++ b/ext/dbm/dbm.c @@ -315,19 +315,12 @@ fdbm_store(obj, keystr, valstr) struct dbmdata *dbmp; DBM *dbm; - if (valstr == Qnil) { - fdbm_delete(obj, keystr); - return Qnil; - } - rb_secure(4); keystr = rb_obj_as_string(keystr); key.dptr = RSTRING(keystr)->ptr; key.dsize = RSTRING(keystr)->len; - if (NIL_P(valstr)) return fdbm_delete(obj, keystr); - valstr = rb_obj_as_string(valstr); val.dptr = RSTRING(valstr)->ptr; val.dsize = RSTRING(valstr)->len; diff --git a/ext/gdbm/gdbm.c b/ext/gdbm/gdbm.c index b38bb8ef48..116b19d18e 100644 --- a/ext/gdbm/gdbm.c +++ b/ext/gdbm/gdbm.c @@ -169,7 +169,7 @@ fgdbm_delete(obj, keystr) if (gdbm_delete(dbm, key)) { dbmp->di_size = -1; - rb_raise(rb_eRuntimeError, "dbm_delete failed"); + rb_raise(rb_eRuntimeError, "gdbm_delete failed"); } else if (dbmp->di_size >= 0) { dbmp->di_size--; @@ -218,7 +218,7 @@ fgdbm_delete_if(obj) valstr = rb_tainted_str_new(val.dptr, val.dsize); if (RTEST(rb_yield(rb_assoc_new(keystr, valstr)))) { if (gdbm_delete(dbm, key)) { - rb_raise(rb_eRuntimeError, "dbm_delete failed"); + rb_raise(rb_eRuntimeError, "gdbm_delete failed"); } } } @@ -240,7 +240,7 @@ fgdbm_clear(obj) for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) { nextkey = gdbm_nextkey(dbm, key); if (gdbm_delete(dbm, key)) { - rb_raise(rb_eRuntimeError, "dbm_delete failed"); + rb_raise(rb_eRuntimeError, "gdbm_delete failed"); } } return obj; @@ -313,19 +313,12 @@ fgdbm_store(obj, keystr, valstr) struct dbmdata *dbmp; GDBM_FILE dbm; - if (valstr == Qnil) { - fgdbm_delete(obj, keystr); - return Qnil; - } - rb_secure(4); keystr = rb_obj_as_string(keystr); key.dptr = RSTRING(keystr)->ptr; key.dsize = RSTRING(keystr)->len; - if (NIL_P(valstr)) return fgdbm_delete(obj, keystr); - valstr = rb_obj_as_string(valstr); val.dptr = RSTRING(valstr)->ptr; val.dsize = RSTRING(valstr)->len; @@ -335,7 +328,7 @@ fgdbm_store(obj, keystr, valstr) dbm = dbmp->di_dbm; if (gdbm_store(dbm, key, val, GDBM_REPLACE)) { if (errno == EPERM) rb_sys_fail(0); - rb_raise(rb_eRuntimeError, "dbm_store failed"); + rb_raise(rb_eRuntimeError, "gdbm_store failed"); } return valstr; diff --git a/ext/socket/socket.c b/ext/socket/socket.c index b38cc48c98..94597055aa 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -115,7 +115,6 @@ sock_new(class, fd) NEWOBJ(sock, struct RFile); OBJSETUP(sock, class, T_FILE); - rb_secure(4); MakeOpenFile(sock, fp); fp->f = rb_fdopen(fd, "r"); #ifdef NT @@ -140,7 +139,9 @@ bsock_shutdown(argc, argv, sock) int how; OpenFile *fptr; - rb_secure(4); + if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) { + rb_raise(rb_eSecurityError, "Insecure: can't shutdown socket"); + } rb_scan_args(argc, argv, "01", &howto); if (howto == Qnil) how = 2; @@ -163,7 +164,9 @@ bsock_close_read(sock) { OpenFile *fptr; - rb_secure(4); + if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) { + rb_raise(rb_eSecurityError, "Insecure: can't close socket"); + } GetOpenFile(sock, fptr); shutdown(fileno(fptr->f), 0); if (fptr->f2 == 0) { @@ -188,7 +191,9 @@ bsock_close_write(sock) { OpenFile *fptr; - rb_secure(4); + if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) { + rb_raise(rb_eSecurityError, "Insecure: can't close socket"); + } GetOpenFile(sock, fptr); if (fptr->f2 == 0) { return rb_io_close(sock); @@ -215,7 +220,6 @@ bsock_setsockopt(sock, lev, optname, val) char *v; int vlen; - rb_secure(2); level = NUM2INT(lev); option = NUM2INT(optname); switch (TYPE(val)) { @@ -794,6 +798,9 @@ socks_s_close(sock) { OpenFile *fptr; + if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) { + rb_raise(rb_eSecurityError, "Insecure: can't close socket"); + } GetOpenFile(sock, fptr); shutdown(fileno(fptr->f), 2); shutdown(fileno(fptr->f2), 2); diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb index c933f9db8b..9f1bae1d40 100644 --- a/ext/tk/lib/tk.rb +++ b/ext/tk/lib/tk.rb @@ -2150,7 +2150,7 @@ class TkListboxpath == NULL) return Qnil; + if (!fptr->path) return Qnil; return rb_str_new2(fptr->path); } @@ -261,7 +261,7 @@ rb_stat(file, st) if (TYPE(file) == T_FILE) { OpenFile *fptr; - rb_secure(4); + rb_secure(2); GetOpenFile(file, fptr); return fstat(fileno(fptr->f), st); } @@ -325,8 +325,9 @@ rb_file_lstat(obj) OpenFile *fptr; struct stat st; - rb_secure(4); + rb_secure(2); GetOpenFile(obj, fptr); + if (!fptr->path) return Qnil; if (lstat(fptr->path, &st) == -1) { rb_sys_fail(fptr->path); } @@ -463,8 +464,8 @@ test_l(obj, fname) Check_SafeStr(fname); if (lstat(RSTRING(fname)->ptr, &st) < 0) return Qfalse; if (S_ISLNK(st.st_mode)) return Qtrue; - #endif + return Qfalse; } @@ -896,11 +897,12 @@ rb_file_chmod(obj, vmode) OpenFile *fptr; int mode; - rb_secure(4); + rb_secure(2); mode = NUM2INT(vmode); GetOpenFile(obj, fptr); #if defined(DJGPP) || defined(NT) || defined(USE_CWGUSI) || defined(__BEOS__) || defined(__EMX__) + if (!fptr->path) return Qnil; if (chmod(fptr->path, mode) == -1) rb_sys_fail(fptr->path); #else @@ -957,9 +959,10 @@ rb_file_chown(obj, owner, group) { OpenFile *fptr; - rb_secure(4); + rb_secure(2); GetOpenFile(obj, fptr); #if defined(DJGPP) || defined(__CYGWIN32__) || defined(NT) || defined(USE_CWGUSI) || defined(__EMX__) + if (!fptr->path) return Qnil; if (chown(fptr->path, NUM2INT(owner), NUM2INT(group)) == -1) rb_sys_fail(fptr->path); #else @@ -1147,7 +1150,7 @@ rb_file_s_umask(argc, argv) #else int omask = 0; - rb_secure(4); + rb_secure(2); if (argc == 0) { omask = umask(0); umask(omask); @@ -1426,7 +1429,7 @@ rb_file_truncate(obj, len) { OpenFile *fptr; - rb_secure(4); + rb_secure(2); GetOpenFile(obj, fptr); if (!(fptr->mode & FMODE_WRITABLE)) { rb_raise(rb_eIOError, "not opened for writing"); @@ -1494,7 +1497,7 @@ rb_file_flock(obj, operation) #else OpenFile *fptr; - rb_secure(4); + rb_secure(2); GetOpenFile(obj, fptr); if (flock(fileno(fptr->f), NUM2INT(operation)) < 0) { diff --git a/gc.c b/gc.c index 6122724175..ad0e2d2ebf 100644 --- a/gc.c +++ b/gc.c @@ -51,6 +51,17 @@ static unsigned long alloc_objects = 0; static int malloc_called = 0; static int free_called = 0; +static int second_mem_error = 0; + +static void +mem_error(mesg) + char *mesg; +{ + if (rb_safe_level() >= 4) { + rb_raise(rb_eNoMemError, mesg); + } + rb_fatal(mesg); +} #ifndef xmalloc void * @@ -72,8 +83,12 @@ xmalloc(size) if (!mem) { rb_gc(); mem = malloc(size); - if (!mem) - rb_fatal("failed to allocate memory"); + if (!mem) { + if (size >= 10 * 1024 * 1024) { + rb_raise(rb_eNoMemError, "try to allocate too big memory"); + } + mem_error("failed to allocate memory"); + } } return mem; @@ -109,7 +124,10 @@ xrealloc(ptr, size) rb_gc(); mem = realloc(ptr, size); if (!mem) - rb_fatal("failed to allocate memory(realloc)"); + if (size >= 10 * 1024 * 1024) { + rb_raise(rb_eNoMemError, "try to re-allocate too big memory"); + } + mem_error("failed to allocate memory(realloc)"); } return mem; @@ -244,11 +262,11 @@ add_heap() heaps = (heaps_used>0)? (RVALUE**)realloc(heaps, heaps_length*sizeof(RVALUE*)): (RVALUE**)malloc(heaps_length*sizeof(RVALUE*)); - if (heaps == 0) rb_fatal("can't alloc memory"); + if (heaps == 0) mem_error("heaps: can't alloc memory"); } p = heaps[heaps_used++] = (RVALUE*)malloc(sizeof(RVALUE)*HEAP_SLOTS); - if (p == 0) rb_fatal("add_heap: can't alloc memory"); + if (p == 0) mem_error("add_heap: can't alloc memory"); pend = p + HEAP_SLOTS; if (lomem == 0 || lomem > p) lomem = p; if (himem < pend) himem = pend; @@ -370,7 +388,7 @@ rb_mark_tbl(tbl) static int mark_hashentry(key, value) - ID key; + VALUE key; VALUE value; { rb_gc_mark(key); diff --git a/hash.c b/hash.c index bebb44b3d2..bfead82e8a 100644 --- a/hash.c +++ b/hash.c @@ -35,7 +35,7 @@ rb_hash_modify(hash) { if (FL_TEST(hash, HASH_FREEZE)) rb_raise(rb_eTypeError, "can't modify frozen hash"); - if (!FL_TEST(hash, FL_TAINT) && rb_safe_level() >= 4) + if (!OBJ_TAINTED(hash) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: can't modify hash"); } @@ -43,6 +43,9 @@ VALUE rb_hash_freeze(hash) VALUE hash; { + if (rb_safe_level() >= 4 && !OBJ_TAINTED(hash)) + rb_raise(rb_eSecurityError, "Insecure: can't freeze hash"); + FL_SET(hash, HASH_FREEZE); return hash; } diff --git a/intern.h b/intern.h index 45bb59e7ba..bcf3921aa9 100644 --- a/intern.h +++ b/intern.h @@ -221,7 +221,7 @@ int yyparse _((void)); ID rb_id_attrset _((ID)); void rb_parser_append_print _((void)); void rb_parser_while_loop _((int, int)); -int rb_is_shvar_id _((ID)); +int rb_is_const_id _((ID)); int rb_is_instance_id _((ID)); VALUE rb_backref_get _((void)); void rb_backref_set _((VALUE)); @@ -323,17 +323,18 @@ VALUE rb_ivar_set _((VALUE, ID, VALUE)); VALUE rb_ivar_defined _((VALUE, ID)); VALUE rb_obj_instance_variables _((VALUE)); VALUE rb_obj_remove_instance_variable _((VALUE, VALUE)); -VALUE rb_mod_shvar_at _((VALUE, VALUE)); -VALUE rb_mod_shvars _((VALUE)); -VALUE rb_mod_shvar_of _((VALUE, VALUE)); -VALUE rb_mod_remove_shvar _((VALUE, VALUE)); -int rb_shvar_defined_at _((VALUE, ID)); +VALUE rb_mod_const_at _((VALUE, VALUE)); +VALUE rb_mod_constants _((VALUE)); +VALUE rb_mod_const_of _((VALUE, VALUE)); +VALUE rb_mod_remove_const _((VALUE, VALUE)); +int rb_const_defined_at _((VALUE, ID)); int rb_autoload_defined _((ID)); -int rb_shvar_defined _((VALUE, ID)); -VALUE rb_shvar_get _((VALUE, ID)); -VALUE rb_shvar_get_at _((VALUE, ID)); -void rb_shvar_set _((VALUE, ID, VALUE)); -VALUE rb_mod_shared_variables _((VALUE)); +int rb_const_defined _((VALUE, ID)); +VALUE rb_const_get _((VALUE, ID)); +VALUE rb_const_get_at _((VALUE, ID)); +void rb_const_set _((VALUE, ID, VALUE)); +VALUE rb_mod_constants _((VALUE)); +void rb_autoload_load _((ID)); /* version.c */ void ruby_show_version _((void)); void ruby_show_copyright _((void)); diff --git a/io.c b/io.c index 1a9d99f5df..1db0cef426 100644 --- a/io.c +++ b/io.c @@ -969,7 +969,9 @@ static VALUE rb_io_close_method(io) VALUE io; { - rb_secure(4); + if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) { + rb_raise(rb_eSecurityError, "Insecure: can't close"); + } rb_io_close(io); return Qnil; } @@ -991,7 +993,9 @@ rb_io_close_read(io) OpenFile *fptr; int n; - rb_secure(4); + if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) { + rb_raise(rb_eSecurityError, "Insecure: can't close"); + } GetOpenFile(io, fptr); if (fptr->f2 == 0 && (fptr->mode & FMODE_WRITABLE)) { rb_raise(rb_eIOError, "closing non-duplex IO for reading"); @@ -1015,7 +1019,9 @@ rb_io_close_write(io) OpenFile *fptr; int n; - rb_secure(4); + if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) { + rb_raise(rb_eSecurityError, "Insecure: can't close"); + } GetOpenFile(io, fptr); if (fptr->f2 == 0 && (fptr->mode & FMODE_READABLE)) { rb_raise(rb_eIOError, "closing non-duplex IO for writing"); @@ -1685,9 +1691,11 @@ rb_io_reopen(io, nfile) char *mode; int fd; - rb_secure(4); - GetOpenFile(io, fptr); nfile = rb_io_get_io(nfile); + if (rb_safe_level() >= 4 && (!OBJ_TAINTED(io) || !OBJ_TAINTED(nfile))) { + rb_raise(rb_eSecurityError, "Insecure: can't reopen"); + } + GetOpenFile(io, fptr); GetOpenFile(nfile, orig); if (fptr == orig) return io; @@ -3070,6 +3078,8 @@ argf_eof() { if (init_p == 0 && !next_argv()) return Qtrue; + if (next_p == -1) + return Qtrue; if (TYPE(current_file) != T_FILE) { return argf_forward(); } diff --git a/misc/ruby-mode.el b/misc/ruby-mode.el index d5dd137af0..098ddd5e04 100644 --- a/misc/ruby-mode.el +++ b/misc/ruby-mode.el @@ -203,7 +203,12 @@ The variable ruby-indent-level controls the amount of indentation. (looking-at "[\\[({]") (and (not modifier) (looking-at "[!?]")) (and (looking-at ruby-symbol-re) - (forward-word -1) + (save-restriction + (let ((p (point))) + (beginning-of-line) + (narrow-to-region (point) p) + (goto-char p) + (forward-word -1))) (if (and (not modifier) (bolp)) t (if (or (looking-at ruby-block-beg-re) diff --git a/object.c b/object.c index be070a9ac2..0851989184 100644 --- a/object.c +++ b/object.c @@ -283,6 +283,7 @@ VALUE rb_obj_taint(obj) VALUE obj; { + rb_secure(4); OBJ_TAINT(obj); return obj; } @@ -688,25 +689,25 @@ rb_mod_attr_accessor(argc, argv, klass) } static VALUE -rb_mod_shvar_get(mod, name) +rb_mod_const_get(mod, name) VALUE mod, name; { - return rb_shvar_get(mod, rb_to_id(name)); + return rb_const_get(mod, rb_to_id(name)); } static VALUE -rb_mod_shvar_set(mod, name, value) +rb_mod_const_set(mod, name, value) VALUE mod, name, value; { - rb_shvar_set(mod, rb_to_id(name), value); + rb_const_set(mod, rb_to_id(name), value); return value; } static VALUE -rb_mod_shvar_defined(mod, name) +rb_mod_const_defined(mod, name) VALUE mod, name; { - return rb_shvar_defined_at(mod, rb_to_id(name)); + return rb_const_defined_at(mod, rb_to_id(name)); } static VALUE @@ -1070,17 +1071,11 @@ Init_Object() rb_define_method(rb_cModule, "protected_instance_methods", rb_class_protected_instance_methods, -1); rb_define_method(rb_cModule, "private_instance_methods", rb_class_private_instance_methods, -1); - rb_define_method(rb_cModule, "shared_variable", rb_mod_shvars, 0); - rb_define_method(rb_cModule, "shared_variable_get", rb_mod_shvar_get, 1); - rb_define_method(rb_cModule, "shared_variable_set", rb_mod_shvar_set, 2); - rb_define_method(rb_cModule, "shared_variable_defined?", rb_mod_shvar_defined, 1); - rb_define_private_method(rb_cModule, "remove_shared_variable", rb_mod_remove_shvar, 1); - /* to be remove at 1.6*/ - rb_define_method(rb_cModule, "constants", rb_mod_shvars, 0); - rb_define_method(rb_cModule, "const_get", rb_mod_shvar_get, 1); - rb_define_method(rb_cModule, "const_set", rb_mod_shvar_set, 2); - rb_define_method(rb_cModule, "const_defined?", rb_mod_shvar_defined, 1); - rb_define_private_method(rb_cModule, "remove_const", rb_mod_remove_shvar, 1); + rb_define_method(rb_cModule, "constants", rb_mod_constants, 0); + rb_define_method(rb_cModule, "const_get", rb_mod_const_get, 1); + rb_define_method(rb_cModule, "const_set", rb_mod_const_set, 2); + rb_define_method(rb_cModule, "const_defined?", rb_mod_const_defined, 1); + rb_define_private_method(rb_cModule, "remove_const", rb_mod_remove_const, 1); rb_define_private_method(rb_cModule, "method_added", rb_obj_dummy, 1); rb_define_method(rb_cClass, "new", rb_class_new_instance, -1); diff --git a/parse.y b/parse.y index 6368a646d4..86cbf78362 100644 --- a/parse.y +++ b/parse.y @@ -26,14 +26,14 @@ #define ID_INSTANCE 0x02 #define ID_GLOBAL 0x03 #define ID_ATTRSET 0x04 -#define ID_SHARED 0x05 +#define ID_CONST 0x05 #define is_notop_id(id) ((id)>LAST_TOKEN) #define is_local_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL) #define is_global_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL) #define is_instance_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE) #define is_attrset_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET) -#define is_shared_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_SHARED) +#define is_const_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST) NODE *ruby_eval_tree_begin = 0; NODE *ruby_eval_tree = 0; @@ -717,7 +717,7 @@ arg : lhs '=' arg $$ = $2; } else { - $$ = call_op($2, tUPLUS, 0); + $$ = call_op($2, tUPLUS, 0, 0); } } | tUMINUS arg @@ -729,7 +729,7 @@ arg : lhs '=' arg $$ = $2; } else { - $$ = call_op($2, tUMINUS, 0); + $$ = call_op($2, tUMINUS, 0, 0); } } | arg '|' arg @@ -791,7 +791,7 @@ arg : lhs '=' arg } | '~' arg { - $$ = call_op($2, '~', 0); + $$ = call_op($2, '~', 0, 0); } | arg tLSHFT arg { @@ -1787,10 +1787,10 @@ yycompile(f) int n; if (!ruby_in_eval && rb_safe_level() == 0 && - rb_shvar_defined(rb_cObject, rb_intern("LINES__"))) { + rb_const_defined(rb_cObject, rb_intern("LINES__"))) { VALUE hash, fname; - hash = rb_shvar_get(rb_cObject, rb_intern("LINES__")); + hash = rb_const_get(rb_cObject, rb_intern("LINES__")); if (TYPE(hash) == T_HASH) { fname = rb_str_new2(f); ruby_debug_lines = rb_hash_aref(hash, fname); @@ -2880,7 +2880,7 @@ yylex() /* binary */ c = nextc(); if (c != '0' && c != '1') { - yyerror("numeric constant with no digits"); + yyerror("numeric literal without digits"); } do { if (c == '_') continue; @@ -3715,7 +3715,7 @@ gettable(id) else if (is_instance_id(id)) { return NEW_IVAR(id); } - else if (is_shared_id(id)) { + else if (is_const_id(id)) { return NEW_CVAR(id); } rb_bug("invalid id for gettable"); @@ -3766,11 +3766,10 @@ assignable(id, val) else if (is_instance_id(id)) { lhs = NEW_IASGN(id, val); } - else if (is_shared_id(id)) { + else if (is_const_id(id)) { if (cur_mid || in_single) - lhs = NEW_CASGN(id, val); - else - lhs = NEW_CDECL(id, val); + yyerror("dynamic constant assignment"); + lhs = NEW_CDECL(id, val); } else { rb_bug("bad id for variable"); @@ -4496,7 +4495,7 @@ rb_intern(name) id = ID_ATTRSET; } else if (ISUPPER(name[0])) { - id = ID_SHARED; + id = ID_CONST; } else { id = ID_LOCAL; @@ -4548,19 +4547,12 @@ rb_id2name(id) return 0; } -int -rb_is_shared_id(id) - ID id; -{ - if (is_shared_id(id)) return Qtrue; - return Qfalse; -} - int rb_is_const_id(id) ID id; { - return rb_is_shared_id(id); + if (is_const_id(id)) return Qtrue; + return Qfalse; } int diff --git a/process.c b/process.c index cecdaa6770..c134a9e95a 100644 --- a/process.c +++ b/process.c @@ -831,6 +831,7 @@ proc_setpgid(obj, pid, pgrp) #ifdef HAVE_SETPGID int ipid, ipgrp; + rb_secure(2); ipid = NUM2INT(pid); ipgrp = NUM2INT(pgrp); @@ -845,8 +846,10 @@ static VALUE proc_setsid() { #ifdef HAVE_SETSID - int pid = setsid(); + int pid; + rb_secure(2); + pid = setsid(); if (pid < 0) rb_sys_fail(0); return INT2FIX(pid); #else @@ -879,6 +882,7 @@ proc_setpriority(obj, which, who, prio) #ifdef HAVE_GETPRIORITY int iwhich, iwho, iprio; + rb_secure(2); iwhich = NUM2INT(which); iwho = NUM2INT(who); iprio = NUM2INT(prio); @@ -995,6 +999,7 @@ static VALUE proc_setegid(obj, egid) VALUE obj, egid; { + rb_secure(2); #ifdef HAVE_SETEGID if (setegid(NUM2INT(egid)) < 0) rb_sys_fail(0); #else diff --git a/range.c b/range.c index 8af5b69d5d..b6cda5dc1e 100644 --- a/range.c +++ b/range.c @@ -138,6 +138,16 @@ range_each(range) else if (TYPE(b) == T_STRING) { rb_str_upto(b, e, EXCL(range)); } + else if (rb_obj_is_kind_of(b, rb_cNumeric)) { + b = rb_Integer(b); + e = rb_Integer(e); + + if (!EXCL(range)) e = rb_funcall(e, '+', 1, INT2FIX(1)); + while (RTEST(rb_funcall(b, '<', 1, e))) { + rb_yield(b); + b = rb_funcall(b, '+', 1, INT2FIX(1)); + } + } else { /* generic each */ VALUE v = b; ID succ = rb_intern("succ"); @@ -286,7 +296,7 @@ range_length(range) VALUE range; { VALUE beg, end; - VALUE size; + long size; beg = rb_ivar_get(range, id_beg); end = rb_ivar_get(range, id_end); @@ -302,7 +312,7 @@ range_length(range) return INT2NUM(NUM2LONG(end) - NUM2LONG(beg) + 1); } } - if (!rb_obj_is_kind_of(beg, rb_cNumeric)) { + if (!rb_obj_is_kind_of(beg, rb_cInteger)) { return rb_length_by_each(range); } size = rb_funcall(end, '-', 1, beg); diff --git a/re.c b/re.c index 9452e42116..46ed3ef4a9 100644 --- a/re.c +++ b/re.c @@ -507,6 +507,32 @@ rb_reg_prepare_re(reg) } } +int +rb_reg_adjust_startpos(reg, str, pos, reverse) + VALUE reg, str; + int pos, reverse; +{ + int range; + + if (may_need_recompile) + rb_reg_prepare_re(reg); + + if (FL_TEST(reg, KCODE_FIXED)) + kcode_set_option(reg); + else if (reg_kcode != curr_kcode) + kcode_reset_option(); + + if (reverse) { + range = -pos; + } + else { + range = RSTRING(str)->len - pos; + } + return re_adjust_startpos(RREGEXP(reg)->ptr, + RSTRING(str)->ptr, RSTRING(str)->len, + pos, range); +} + int rb_reg_search(reg, str, pos, reverse) VALUE reg, str; diff --git a/re.h b/re.h index 9d3b77f519..2ce2134ccc 100644 --- a/re.h +++ b/re.h @@ -32,6 +32,7 @@ int rb_str_cicmp _((VALUE, VALUE)); VALUE rb_reg_regcomp _((VALUE)); int rb_reg_search _((VALUE, VALUE, int, int)); VALUE rb_reg_regsub _((VALUE, VALUE, struct re_registers *)); +int rb_reg_adjust_startpos _((VALUE, VALUE, int, int)); int rb_kcode _((void)); diff --git a/regex.c b/regex.c index 834d97b574..ea08cb5ede 100644 --- a/regex.c +++ b/regex.c @@ -2922,35 +2922,15 @@ re_compile_fastmap(bufp) FREE_AND_RETURN_VOID(stackb); } - -/* Using the compiled pattern in BUFP->buffer, first tries to match - STRING, starting first at index STARTPOS, then at STARTPOS + 1, and - so on. RANGE is the number of places to try before giving up. If - RANGE is negative, it searches backwards, i.e., the starting - positions tried are STARTPOS, STARTPOS - 1, etc. STRING is of SIZE. - In REGS, return the indices of STRING that matched the entire - BUFP->buffer and its contained subexpressions. - - The value returned is the position in the strings at which the match - was found, or -1 if no match was found, or -2 if error (such as - failure stack overflow). */ - +/* adjust startpos value to the position between characters. */ int -re_search(bufp, string, size, startpos, range, regs) +re_adjust_startpos(bufp, string, size, startpos, range) struct re_pattern_buffer *bufp; const char *string; int size, startpos, range; - struct re_registers *regs; { - register char *fastmap = bufp->fastmap; - int val, anchor = 0; - - /* Check for out-of-range starting position. */ - if (startpos < 0 || startpos > size) - return -1; - /* Update the fastmap now if not correct already. */ - if (fastmap && !bufp->fastmap_accurate) { + if (!bufp->fastmap_accurate) { re_compile_fastmap(bufp); } @@ -2980,6 +2960,41 @@ re_search(bufp, string, size, startpos, range, regs) } } } + return startpos; +} + + +/* Using the compiled pattern in BUFP->buffer, first tries to match + STRING, starting first at index STARTPOS, then at STARTPOS + 1, and + so on. RANGE is the number of places to try before giving up. If + RANGE is negative, it searches backwards, i.e., the starting + positions tried are STARTPOS, STARTPOS - 1, etc. STRING is of SIZE. + In REGS, return the indices of STRING that matched the entire + BUFP->buffer and its contained subexpressions. + + The value returned is the position in the strings at which the match + was found, or -1 if no match was found, or -2 if error (such as + failure stack overflow). */ + +int +re_search(bufp, string, size, startpos, range, regs) + struct re_pattern_buffer *bufp; + const char *string; + int size, startpos, range; + struct re_registers *regs; +{ + register char *fastmap = bufp->fastmap; + int val, anchor = 0; + + /* Check for out-of-range starting position. */ + if (startpos < 0 || startpos > size) + return -1; + + /* Update the fastmap now if not correct already. */ + if (fastmap && !bufp->fastmap_accurate) { + re_compile_fastmap(bufp); + } + /* If the search isn't to be a backwards one, don't waste time in a search for a pattern that must be anchored. */ diff --git a/regex.h b/regex.h index 0d91273241..2386d2daa8 100644 --- a/regex.h +++ b/regex.h @@ -28,6 +28,7 @@ /* symbol mangling for ruby */ #ifdef RUBY +# define re_adjust_startpos ruby_re_adjust_startpos # define re_compile_fastmap ruby_re_compile_fastmap # define re_compile_pattern ruby_re_compile_pattern # define re_copy_registers ruby_re_copy_registers @@ -186,6 +187,7 @@ typedef struct extern char *re_compile_pattern (const char *, int, struct re_pattern_buffer *); void re_free_pattern (struct re_pattern_buffer *); /* Is this really advertised? */ +extern int re_adjust_startpos (struct re_pattern_buffer *, const char*, int, int, int); extern void re_compile_fastmap (struct re_pattern_buffer *); extern int re_search (struct re_pattern_buffer *, const char*, int, int, int, struct re_registers *); @@ -206,6 +208,7 @@ extern int re_exec (const char *); extern char *re_compile_pattern (); void re_free_regexp (); /* Is this really advertised? */ +extern int re_adjust_startpos (); extern void re_compile_fastmap (); extern int re_search (); extern int re_match (); diff --git a/ruby.h b/ruby.h index adbcff6c75..fd87c0bcb2 100644 --- a/ruby.h +++ b/ruby.h @@ -89,7 +89,7 @@ extern "C" { ---->> ruby requires sizeof(void*) == sizeof(long) to be compiled. <<---- #endif typedef unsigned long VALUE; -typedef unsigned int ID; +typedef unsigned long ID; #ifdef __STDC__ # include @@ -117,6 +117,8 @@ typedef unsigned int ID; #define INT2FIX(i) (VALUE)(((long)(i))<<1 | FIXNUM_FLAG) VALUE rb_int2inum _((long)); #define INT2NUM(v) rb_int2inum(v) +VALUE rb_uint2inum _((unsigned long)); +#define UINT2NUM(v) rb_uint2inum(v) #define FIX2LONG(x) RSHIFT((long)x,1) #define FIX2ULONG(x) (((unsigned long)(x))>>1) @@ -271,14 +273,14 @@ struct RFile { struct RData { struct RBasic basic; - void (*dmark)(); - void (*dfree)(); + void (*dmark) _((void*)); + void (*dfree) _((void*)); void *data; }; #define DATA_PTR(dta) (RDATA(dta)->data) -VALUE rb_data_object_alloc _((VALUE,void*,void (*)(),void (*)())); +VALUE rb_data_object_alloc _((VALUE,void*,void (*) _((void*)),void (*) _((void*)))); #define Data_Make_Struct(klass,type,mark,free,sval) (\ sval = ALLOC(type),\ memset(sval, 0, sizeof(type)),\ @@ -375,8 +377,8 @@ void rb_define_variable _((const char*,VALUE*)); void rb_define_virtual_variable _((const char*,VALUE(*)(),void(*)())); void rb_define_hooked_variable _((const char*,VALUE*,VALUE(*)(),void(*)())); void rb_define_readonly_variable _((const char*,VALUE*)); -void rb_define_shared_variable _((VALUE,const char*,VALUE)); -void rb_define_global_shared_variable _((const char*,VALUE)); +void rb_define_constants _((VALUE,const char*,VALUE)); +void rb_define_global_constants _((const char*,VALUE)); void rb_define_method _((VALUE,const char*,VALUE(*)(),int)); void rb_define_module_function _((VALUE,const char*,VALUE(*)(),int)); @@ -494,6 +496,7 @@ EXTERN VALUE rb_eSystemCallError; EXTERN VALUE rb_eTypeError; EXTERN VALUE rb_eZeroDivError; EXTERN VALUE rb_eNotImpError; +EXTERN VALUE rb_eNoMemError; EXTERN VALUE rb_eFloatDomainError; #if defined(__GNUC__) && __GNUC__ >= 2 && !defined(RUBY_NO_INLINE) diff --git a/string.c b/string.c index df416877c3..97f4f89b69 100644 --- a/string.c +++ b/string.c @@ -66,7 +66,7 @@ rb_tainted_str_new(ptr, len) { VALUE str = rb_str_new(ptr, len); - FL_SET(str, FL_TAINT); + OBJ_TAINT(str); return str; } @@ -76,7 +76,7 @@ rb_tainted_str_new2(ptr) { VALUE str = rb_str_new2(ptr); - FL_SET(str, FL_TAINT); + OBJ_TAINT(str); return str; } @@ -112,8 +112,8 @@ rb_str_new4(orig) str->ptr = RSTRING(orig)->ptr; RSTRING(orig)->orig = (VALUE)str; str->orig = 0; - if (FL_TEST(orig, FL_TAINT)) { - FL_SET(str, FL_TAINT); + if (OBJ_TAINTED(orig)) { + OBJ_TAINT(str); } FL_SET(str, STR_FREEZE); return (VALUE)str; @@ -213,7 +213,7 @@ rb_str_s_new(klass, orig) } if (rb_safe_level() >= 3) { - FL_SET(str, FL_TAINT); + OBJ_TAINT(str); } return (VALUE)str; @@ -334,7 +334,7 @@ rb_str_modify(str) if (FL_TEST(str, STR_FREEZE)) rb_raise(rb_eTypeError, "can't modify frozen string"); - if (!FL_TEST(str, FL_TAINT) && rb_safe_level() >= 4) + if (!OBJ_TAINTED(str) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: can't modify string"); if (!RSTRING(str)->orig || FL_TEST(str, STR_NO_ORIG)) return; ptr = RSTRING(str)->ptr; @@ -350,6 +350,9 @@ VALUE rb_str_freeze(str) VALUE str; { + if (rb_safe_level() >= 4 && !OBJ_TAINTED(str)) + rb_raise(rb_eSecurityError, "Insecure: can't freeze string"); + FL_SET(str, STR_FREEZE); return str; } @@ -585,6 +588,7 @@ rb_str_index_method(argc, argv, str) switch (TYPE(sub)) { case T_REGEXP: + pos = rb_reg_adjust_startpos(sub, str, pos, 0); pos = rb_reg_search(sub, str, pos, 0); break; @@ -635,6 +639,7 @@ rb_str_rindex(argc, argv, str) switch (TYPE(sub)) { case T_REGEXP: if (RREGEXP(sub)->len) { + pos = rb_reg_adjust_startpos(sub, str, pos, 1); pos = rb_reg_search(sub, str, pos, 1); } if (pos >= 0) return INT2NUM(pos); diff --git a/struct.c b/struct.c index b14b82065c..1114577729 100644 --- a/struct.c +++ b/struct.c @@ -161,7 +161,7 @@ make_struct(name, member, klass) else { char *cname = STR2CSTR(name); id = rb_intern(cname); - if (!rb_is_shared_id(id)) { + if (!rb_is_const_id(id)) { rb_raise(rb_eNameError, "identifier %s needs to be constant", cname); } nstr = rb_define_class_under(klass, cname, klass); @@ -207,7 +207,8 @@ rb_struct_define(name, va_alist) VALUE nm, ary; char *mem; - nm = rb_str_new2(name); + if (!name) nm = Qnil; + else nm = rb_str_new2(name); ary = rb_ary_new(); va_init_list(ar, name); @@ -224,16 +225,23 @@ static VALUE rb_struct_s_def(argc, argv, klass) int argc; VALUE *argv; + VALUE klass; { VALUE name, rest; long i; VALUE st; + ID id; rb_scan_args(argc, argv, "1*", &name, &rest); for (i=0; ilen; i++) { - ID id = rb_to_id(RARRAY(rest)->ptr[i]); + id = rb_to_id(RARRAY(rest)->ptr[i]); RARRAY(rest)->ptr[i] = INT2FIX(id); } + if (TYPE(name) != T_STRING) { + id = rb_to_id(name); + rb_ary_unshift(rest, INT2FIX(id)); + name = Qnil; + } st = make_struct(name, rest, klass); return st; diff --git a/variable.c b/variable.c index b29ce55cce..fef84f7128 100644 --- a/variable.c +++ b/variable.c @@ -44,7 +44,7 @@ fc_i(key, value, res) VALUE path; char *name; - if (!rb_is_shared_id(key)) return ST_CONTINUE; + if (!rb_is_const_id(key)) return ST_CONTINUE; name = rb_id2name(key); if (res->path) { @@ -226,7 +226,7 @@ rb_autoload_id(id, filename) ID id; const char *filename; { - if (!rb_is_shared_id(id)) { + if (!rb_is_const_id(id)) { rb_raise(rb_eNameError, "autoload must be constant name", rb_id2name(id)); } @@ -858,7 +858,7 @@ rb_ivar_get(obj, id) { VALUE val; - if (!FL_TEST(obj, FL_TAINT) && rb_safe_level() >= 4) + if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: can't access instance variable"); switch (TYPE(obj)) { case T_OBJECT: @@ -873,7 +873,7 @@ rb_ivar_get(obj, id) break; } if (ruby_verbose) { - rb_warning("instance var %s not initialized", rb_id2name(id)); + rb_warning("instance variable %s not initialized", rb_id2name(id)); } return Qnil; } @@ -884,7 +884,7 @@ rb_ivar_set(obj, id, val) ID id; VALUE val; { - if (!FL_TEST(obj, FL_TAINT) && rb_safe_level() >= 4) + if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable"); switch (TYPE(obj)) { case T_OBJECT: @@ -936,10 +936,11 @@ VALUE rb_obj_instance_variables(obj) VALUE obj; { - VALUE ary = rb_ary_new(); + VALUE ary; - if (!FL_TEST(obj, FL_TAINT) && rb_safe_level() >= 4) + if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: can't get metainfo"); + ary = rb_ary_new(); switch (TYPE(obj)) { case T_OBJECT: case T_CLASS: @@ -969,7 +970,7 @@ rb_obj_remove_instance_variable(obj, name) VALUE val = Qnil; ID id = rb_to_id(name); - if (!FL_TEST(obj, FL_TAINT) && rb_safe_level() >= 4) + if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable"); if (!rb_is_instance_id(id)) { rb_raise(rb_eNameError, "`%s' is not an instance variable", @@ -993,7 +994,7 @@ rb_obj_remove_instance_variable(obj, name) } VALUE -rb_shvar_get_at(klass, id) +rb_const_get_at(klass, id) VALUE klass; ID id; { @@ -1003,7 +1004,7 @@ rb_shvar_get_at(klass, id) return value; } if (klass == rb_cObject) { - return rb_shvar_get(klass, id); + return rb_const_get(klass, id); } rb_raise(rb_eNameError, "uninitialized constant %s::%s", RSTRING(rb_class_path(klass))->ptr, @@ -1012,16 +1013,21 @@ rb_shvar_get_at(klass, id) } -VALUE -rb_const_get_at(klass, id) - VALUE klass; +void +rb_autoload_load(id) ID id; { - return rb_shvar_get_at(klass, id); + char *modname; + VALUE module; + + st_delete(autoload_tbl, &id, &modname); + module = rb_str_new2(modname); + free(modname); + rb_f_require(Qnil, module); } VALUE -rb_shvar_get(klass, id) +rb_const_get(klass, id) VALUE klass; ID id; { @@ -1036,7 +1042,7 @@ rb_shvar_get(klass, id) tmp = RCLASS(tmp)->super; } if (BUILTIN_TYPE(klass) == T_MODULE) { - return rb_shvar_get(rb_cObject, id); + return rb_const_get(rb_cObject, id); } /* pre-defined class */ @@ -1044,14 +1050,8 @@ rb_shvar_get(klass, id) /* autoload */ if (autoload_tbl && st_lookup(autoload_tbl, id, 0)) { - char *modname; - VALUE module; - - st_delete(autoload_tbl, &id, &modname); - module = rb_str_new2(modname); - free(modname); - rb_f_require(Qnil, module); - return rb_shvar_get(klass, id); + rb_autoload_load(id); + return rb_const_get(klass, id); } /* Uninitialized constant */ @@ -1065,21 +1065,13 @@ rb_shvar_get(klass, id) return Qnil; /* not reached */ } -VALUE -rb_const_get(klass, id) - VALUE klass; - ID id; -{ - return rb_shvar_get(klass, id); -} - static int sv_i(key, value, ary) ID key; VALUE value; VALUE ary; { - if (rb_is_shared_id(key)) { + if (rb_is_const_id(key)) { VALUE kval = rb_str_new2(rb_id2name(key)); if (!rb_ary_includes(ary, kval)) { rb_ary_push(ary, kval); @@ -1089,20 +1081,22 @@ sv_i(key, value, ary) } VALUE -rb_mod_remove_shvar(mod, name) +rb_mod_remove_const(mod, name) VALUE mod, name; { ID id = rb_to_id(name); VALUE val; - if (!rb_is_shared_id(id)) { - rb_raise(rb_eNameError, "`%s' is not shared variable", rb_id2name(id)); + if (!OBJ_TAINTED(mod) && rb_safe_level() >= 4) + rb_raise(rb_eSecurityError, "Insecure: can't remove constant"); + if (!rb_is_const_id(id)) { + rb_raise(rb_eNameError, "`%s' is not constant", rb_id2name(id)); } if (RCLASS(mod)->iv_tbl && st_delete(ROBJECT(mod)->iv_tbl, &id, &val)) { return val; } - if (rb_shvar_defined_at(mod, id)) { + if (rb_const_defined_at(mod, id)) { rb_raise(rb_eNameError, "cannot remove %s::%s", rb_class2name(mod), rb_id2name(id)); } @@ -1111,13 +1105,6 @@ rb_mod_remove_shvar(mod, name) return Qnil; /* not reached */ } -VALUE -rb_mod_remove_const(mod, name) - VALUE mod, name; -{ - return rb_mod_remove_shvar(mod, name); -} - static int autoload_i(key, name, ary) ID key; @@ -1132,10 +1119,10 @@ autoload_i(key, name, ary) } VALUE -rb_mod_shvar_at(mod, ary) +rb_mod_const_at(mod, ary) VALUE mod, ary; { - if (!FL_TEST(mod, FL_TAINT) && rb_safe_level() >= 4) + if (!OBJ_TAINTED(mod) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: can't get metainfo"); if (RCLASS(mod)->iv_tbl) { st_foreach(RCLASS(mod)->iv_tbl, sv_i, ary); @@ -1150,50 +1137,28 @@ rb_mod_shvar_at(mod, ary) } VALUE -rb_mod_const_at(mod, ary) - VALUE mod, ary; -{ - return rb_mod_shvar_at(mod, ary); -} - -VALUE -rb_mod_shvar_of(mod, ary) +rb_mod_const_of(mod, ary) VALUE mod; VALUE ary; { - rb_mod_shvar_at(mod, ary); + rb_mod_const_at(mod, ary); for (;;) { mod = RCLASS(mod)->super; if (!mod) break; - rb_mod_shvar_at(mod, ary); + rb_mod_const_at(mod, ary); } return ary; } -VALUE -rb_mod_const_of(mod, ary) - VALUE mod; - VALUE ary; -{ - return rb_mod_shvar_of(mod, ary); -} - -VALUE -rb_mod_shvars(mod) - VALUE mod; -{ - return rb_mod_shvar_of(mod, rb_ary_new()); -} - VALUE rb_mod_constants(mod) VALUE mod; { - return rb_mod_shvars(mod); + return rb_mod_const_of(mod, rb_ary_new()); } int -rb_shvar_defined_at(klass, id) +rb_const_defined_at(klass, id) VALUE klass; ID id; { @@ -1201,19 +1166,11 @@ rb_shvar_defined_at(klass, id) return Qtrue; } if (klass == rb_cObject) { - return rb_shvar_defined(klass, id); + return rb_const_defined(klass, id); } return Qfalse; } -int -rb_const_defined_at(klass, id) - VALUE klass; - ID id; -{ - return rb_shvar_defined_at(klass, id); -} - int rb_autoload_defined(id) ID id; @@ -1224,7 +1181,7 @@ rb_autoload_defined(id) } int -rb_shvar_defined(klass, id) +rb_const_defined(klass, id) VALUE klass; ID id; { @@ -1237,28 +1194,20 @@ rb_shvar_defined(klass, id) tmp = RCLASS(tmp)->super; } if (BUILTIN_TYPE(klass) == T_MODULE) { - return rb_shvar_defined(rb_cObject, id); + return rb_const_defined(rb_cObject, id); } if (st_lookup(rb_class_tbl, id, 0)) return Qtrue; return rb_autoload_defined(id); } -int -rb_const_defined(klass, id) - VALUE klass; - ID id; -{ - return rb_shvar_defined(klass, id); -} - void -rb_shvar_set(klass, id, val) +rb_const_set(klass, id, val) VALUE klass; ID id; VALUE val; { - if (!FL_TEST(klass, FL_TAINT) && rb_safe_level() >= 4) + if (!OBJ_TAINTED(klass) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: can't set constant"); if (!RCLASS(klass)->iv_tbl) { RCLASS(klass)->iv_tbl = st_init_numtable(); @@ -1268,16 +1217,7 @@ rb_shvar_set(klass, id, val) } void -rb_const_set(klass, id, val) - VALUE klass; - ID id; - VALUE val; -{ - rb_shvar_set(klass, id, val); -} - -void -rb_shvar_assign(klass, id, val) +rb_const_assign(klass, id, val) VALUE klass; ID id; VALUE val; @@ -1329,19 +1269,10 @@ rb_define_const(klass, name, val) if (klass == rb_cObject) { rb_secure(4); } - if (!rb_is_shared_id(id)) { - rb_raise(rb_eNameError, "wrong shared variable name %s", name); + if (!rb_is_const_id(id)) { + rb_raise(rb_eNameError, "wrong constant name %s", name); } - rb_shvar_set(klass, id, val); -} - -void -rb_define_shvar(klass, name, val) - VALUE klass; - const char *name; - VALUE val; -{ - rb_define_const(klass, name, val); + rb_const_set(klass, id, val); } void @@ -1352,14 +1283,6 @@ rb_define_global_const(name, val) rb_define_const(rb_cObject, name, val); } -void -rb_define_global_shvar(name, val) - const char *name; - VALUE val; -{ - rb_define_global_const(name, val); -} - VALUE rb_iv_get(obj, name) VALUE obj; diff --git a/version.h b/version.h index 2a54764a1a..f8418db95a 100644 --- a/version.h +++ b/version.h @@ -1,4 +1,4 @@ #define RUBY_VERSION "1.5.0" -#define RUBY_RELEASE_DATE "1999-12-07" +#define RUBY_RELEASE_DATE "1999-12-14" #define RUBY_VERSION_CODE 150 -#define RUBY_RELEASE_CODE 19991207 +#define RUBY_RELEASE_CODE 19991214 diff --git a/win32/config.status b/win32/config.status index 0ffddc901c..0e79324ae6 100644 --- a/win32/config.status +++ b/win32/config.status @@ -35,7 +35,7 @@ s%@RANLIB@%rem%g s%@AR@%lib -nologo%g s%@LN_S@%%g s%@SET_MAKE@%%g -s%@LIBOBJS@% crypt.obj alloca.obj win32.obj fnmatch.obj isinf.obj isnan.obj%g +s%@LIBOBJS@% crypt.obj alloca.obj win32.obj isinf.obj isnan.obj%g s%@ALLOCA@%%g s%@DEFAULT_KCODE@%%g s%@EXEEXT@%.exe%g -- cgit v1.2.3