1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@587 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 1999-12-14 06:50:43 +00:00
parent c18d3740a9
commit 9d228b13de
34 changed files with 649 additions and 508 deletions

View file

@ -1,3 +1,55 @@
Mon Dec 13 15:15:31 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
* 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 <matz@netlab.co.jp>
* 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 <eguchi@shizuokanet.ne.jp>
* error.c (exc_set_backtrace): forgot to declare a VALUE argument.
Thu Dec 9 14:19:31 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
* 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 <matz@netlab.co.jp>
* 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 <matz@netlab.co.jp>
* eval.c (rb_eval): should try autoloading before defining
class/module at the toplevel.
Tue Dec 7 22:15:30 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
* 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 <matz@netlab.co.jp> Tue Dec 7 11:16:30 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
* eval.c (Init_eval): calculate stack limit from rlimit where * eval.c (Init_eval): calculate stack limit from rlimit where

2
README
View file

@ -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: The URL of the Ruby home-page is:
http://www.netlab.co.jp/ruby/ http://www.ruby-lang.org/
* The Author * The Author

View file

@ -44,7 +44,7 @@ Ruby
RubyのホームページのURLは RubyのホームページのURLは
http://www.netlab.co.jp/ruby/jp/ http://www.ruby-lang.org/
です. です.

View file

@ -49,7 +49,7 @@ rb_ary_modify(ary)
rb_raise(rb_eTypeError, "can't modify frozen array"); rb_raise(rb_eTypeError, "can't modify frozen array");
if (FL_TEST(ary, ARY_TMPLOCK)) if (FL_TEST(ary, ARY_TMPLOCK))
rb_raise(rb_eTypeError, "can't modify array during sort"); 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"); rb_raise(rb_eSecurityError, "Insecure: can't modify array");
} }
@ -57,6 +57,9 @@ VALUE
rb_ary_freeze(ary) rb_ary_freeze(ary)
VALUE 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); FL_SET(ary, ARY_FREEZE);
return ary; return ary;
} }

27
class.c
View file

@ -130,7 +130,7 @@ rb_define_class_under(outer, name, super)
id = rb_intern(name); id = rb_intern(name);
klass = rb_define_class_id(id, super); 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); rb_set_class_path(klass, outer, name);
return klass; return klass;
@ -186,7 +186,7 @@ rb_define_module_under(outer, name)
id = rb_intern(name); id = rb_intern(name);
module = rb_define_module_id(id); 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); rb_set_class_path(module, outer, name);
return module; return module;
@ -368,7 +368,7 @@ method_list(mod, option, func)
VALUE klass; VALUE klass;
VALUE *p, *q, *pend; 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"); rb_raise(rb_eSecurityError, "Insecure: can't get metainfo");
ary = rb_ary_new(); ary = rb_ary_new();
for (klass = mod; klass; klass = RCLASS(klass)->super) { for (klass = mod; klass; klass = RCLASS(klass)->super) {
@ -431,7 +431,7 @@ rb_obj_singleton_methods(obj)
VALUE klass; VALUE klass;
VALUE *p, *q, *pend; 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"); rb_raise(rb_eSecurityError, "Insecure: can't get metainfo");
ary = rb_ary_new(); ary = rb_ary_new();
klass = CLASS_OF(obj); klass = CLASS_OF(obj);
@ -510,15 +510,26 @@ VALUE
rb_singleton_class(obj) rb_singleton_class(obj)
VALUE obj; VALUE obj;
{ {
VALUE klass;
if (rb_special_const_p(obj)) { if (rb_special_const_p(obj)) {
rb_raise(rb_eTypeError, "can't define singleton"); rb_raise(rb_eTypeError, "can't define singleton");
} }
if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON)) { if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON)) {
return RBASIC(obj)->klass; klass = RBASIC(obj)->klass;
} }
RBASIC(obj)->klass = rb_singleton_class_new(RBASIC(obj)->klass); else {
rb_singleton_class_attached(RBASIC(obj)->klass, obj); klass = rb_singleton_class_new(RBASIC(obj)->klass);
return RBASIC(obj)->klass; RBASIC(obj)->klass = klass;
rb_singleton_class_attached(klass, obj);
}
if (OBJ_TAINTED(obj)) {
OBJ_TAINT(klass);
}
else {
FL_UNSET(klass, FL_TAINT);
}
return klass;
} }
void void

4
configure vendored
View file

@ -3783,7 +3783,7 @@ else
int int
main() main()
{ {
if (-1==(-1>>(unsigned)1)) if (-1==(-1>>1))
return 0; return 0;
return 1; return 1;
} }
@ -3806,7 +3806,7 @@ fi
echo "$ac_t""$rb_cv_rshift_sign" 1>&6 echo "$ac_t""$rb_cv_rshift_sign" 1>&6
if test "$rb_cv_rshift_sign" = yes; then if test "$rb_cv_rshift_sign" = yes; then
cat >> confdefs.h <<\EOF cat >> confdefs.h <<\EOF
#define RSHIFT(x,y) ((x)>>y) #define RSHIFT(x,y) ((x)>>(int)y)
EOF EOF
else else

View file

@ -260,7 +260,7 @@ AC_CACHE_CHECK(whether right shift preserve sign bit, rb_cv_rshift_sign,
int int
main() main()
{ {
if (-1==(-1>>(unsigned)1)) if (-1==(-1>>1))
return 0; return 0;
return 1; return 1;
} }
@ -269,7 +269,7 @@ main()
rb_cv_rshift_sign=no, rb_cv_rshift_sign=no,
rb_cv_rshift_sign=yes)]) rb_cv_rshift_sign=yes)])
if test "$rb_cv_rshift_sign" = yes; then if test "$rb_cv_rshift_sign" = yes; then
AC_DEFINE(RSHIFT(x,y), ((x)>>y)) AC_DEFINE(RSHIFT(x,y), ((x)>>(int)y))
else else
AC_DEFINE(RSHIFT(x,y), (((x)<0) ? ~((~(x))>>y) : (x)>>y)) AC_DEFINE(RSHIFT(x,y), (((x)<0) ? ~((~(x))>>y) : (x)>>y))
fi fi

4
dir.c
View file

@ -435,7 +435,6 @@ dir_s_mkdir(argc, argv, obj)
VALUE path, vmode; VALUE path, vmode;
int mode; int mode;
rb_secure(2);
if (rb_scan_args(argc, argv, "11", &path, &vmode) == 2) { if (rb_scan_args(argc, argv, "11", &path, &vmode) == 2) {
mode = NUM2INT(vmode); mode = NUM2INT(vmode);
} }
@ -444,6 +443,7 @@ dir_s_mkdir(argc, argv, obj)
} }
Check_SafeStr(path); Check_SafeStr(path);
rb_secure(2);
#if !defined(NT) && !defined(USE_CWGUSI) #if !defined(NT) && !defined(USE_CWGUSI)
if (mkdir(RSTRING(path)->ptr, mode) == -1) if (mkdir(RSTRING(path)->ptr, mode) == -1)
rb_sys_fail(RSTRING(path)->ptr); rb_sys_fail(RSTRING(path)->ptr);
@ -459,8 +459,8 @@ static VALUE
dir_s_rmdir(obj, dir) dir_s_rmdir(obj, dir)
VALUE obj, dir; VALUE obj, dir;
{ {
rb_secure(2);
Check_SafeStr(dir); Check_SafeStr(dir);
rb_secure(2);
if (rmdir(RSTRING(dir)->ptr) < 0) if (rmdir(RSTRING(dir)->ptr) < 0)
rb_sys_fail(RSTRING(dir)->ptr); rb_sys_fail(RSTRING(dir)->ptr);

View file

@ -247,6 +247,7 @@ VALUE rb_eIndexError;
VALUE rb_eLoadError; VALUE rb_eLoadError;
VALUE rb_eSecurityError; VALUE rb_eSecurityError;
VALUE rb_eNotImpError; VALUE rb_eNotImpError;
VALUE rb_eNoMemError;
VALUE rb_eSystemCallError; VALUE rb_eSystemCallError;
VALUE rb_mErrno; VALUE rb_mErrno;
@ -387,6 +388,7 @@ check_backtrace(bt)
static VALUE static VALUE
exc_set_backtrace(exc, bt) exc_set_backtrace(exc, bt)
VALUE exc; VALUE exc;
VALUE bt;
{ {
return rb_iv_set(exc, "bt", check_backtrace(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_eRuntimeError = rb_define_class("RuntimeError", rb_eStandardError);
rb_eSecurityError = rb_define_class("SecurityError", rb_eStandardError); rb_eSecurityError = rb_define_class("SecurityError", rb_eStandardError);
rb_eNotImpError = rb_define_class("NotImplementError", rb_eException); rb_eNotImpError = rb_define_class("NotImplementError", rb_eException);
rb_eNoMemError = rb_define_class("NoMemoryError", rb_eException);
init_syserr(); init_syserr();
} }

453
eval.c
View file

@ -90,6 +90,73 @@ static int scope_vmode;
#define SCOPE_SET(f) do {scope_vmode=(f);} while(0) #define SCOPE_SET(f) do {scope_vmode=(f);} while(0)
#define SCOPE_TEST(f) (scope_vmode&(f)) #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 _((VALUE, ID)) NORETURN;
static void static void
print_undef(klass, id) print_undef(klass, id)
@ -158,6 +225,9 @@ rb_add_method(klass, mid, node, noex)
if (klass == rb_cObject) { if (klass == rb_cObject) {
rb_secure(4); rb_secure(4);
} }
if (safe_level >= 4 && !OBJ_TAINTED(klass)) {
rb_raise(rb_eSecurityError, "Insecure: can't define method");
}
body = NEW_METHOD(node, noex); body = NEW_METHOD(node, noex);
st_insert(RCLASS(klass)->m_tbl, mid, body); st_insert(RCLASS(klass)->m_tbl, mid, body);
} }
@ -225,38 +295,6 @@ rb_get_method_body(klassp, idp, noexp)
return body; 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 static void
remove_method(klass, mid) remove_method(klass, mid)
VALUE klass; VALUE klass;
@ -267,6 +305,9 @@ remove_method(klass, mid)
if (klass == rb_cObject) { if (klass == rb_cObject) {
rb_secure(4); 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)) { if (!st_delete(RCLASS(klass)->m_tbl, &mid, &body)) {
rb_raise(rb_eNameError, "method `%s' not defined in %s", rb_raise(rb_eNameError, "method `%s' not defined in %s",
rb_id2name(mid), rb_class2name(klass)); rb_id2name(mid), rb_class2name(klass));
@ -282,6 +323,14 @@ rb_remove_method(klass, name)
remove_method(klass, rb_intern(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 void
rb_disable_super(klass, name) rb_disable_super(klass, name)
VALUE klass; VALUE klass;
@ -740,75 +789,6 @@ static VALUE module_setup _((VALUE,NODE*));
static VALUE massign _((VALUE,NODE*,VALUE,int)); static VALUE massign _((VALUE,NODE*,VALUE,int));
static void assign _((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 VALUE trace_func = 0;
static void call_trace_func _((char*,char*,int,VALUE,ID,VALUE)); static void call_trace_func _((char*,char*,int,VALUE,ID,VALUE));
@ -1322,7 +1302,7 @@ superclass(self, node)
} }
static VALUE static VALUE
ev_shvar_defined(cref, id) ev_const_defined(cref, id)
NODE *cref; NODE *cref;
ID id; ID id;
{ {
@ -1337,11 +1317,11 @@ ev_shvar_defined(cref, id)
} }
cbase = cbase->nd_next; cbase = cbase->nd_next;
} }
return rb_shvar_defined(cref->nd_clss, id); return rb_const_defined(cref->nd_clss, id);
} }
static VALUE static VALUE
ev_shvar_get(cref, id) ev_const_get(cref, id)
NODE *cref; NODE *cref;
ID id; ID id;
{ {
@ -1356,11 +1336,11 @@ ev_shvar_get(cref, id)
} }
cbase = cbase->nd_next; cbase = cbase->nd_next;
} }
return rb_shvar_get(cref->nd_clss, id); return rb_const_get(cref->nd_clss, id);
} }
static VALUE static VALUE
ev_shvar_set(cref, id, val) ev_const_set(cref, id, val)
NODE *cref; NODE *cref;
ID id; ID id;
VALUE val; VALUE val;
@ -1377,7 +1357,7 @@ ev_shvar_set(cref, id, val)
} }
cbase = cbase->nd_next; cbase = cbase->nd_next;
} }
rb_shvar_assign(cbase->nd_clss, id, val); rb_const_assign(cbase->nd_clss, id, val);
return val; return val;
} }
@ -1395,47 +1375,103 @@ rb_mod_nesting()
} }
static VALUE static VALUE
rb_mod_s_shvars() rb_mod_s_constants()
{ {
NODE *cbase = (NODE*)ruby_frame->cbase; NODE *cbase = (NODE*)ruby_frame->cbase;
VALUE ary = rb_ary_new(); VALUE ary = rb_ary_new();
while (cbase && cbase->nd_clss != rb_cObject) { 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; 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; return ary;
} }
static VALUE void
rb_mod_remove_method(mod, name) rb_undef(klass, id)
VALUE mod, name; VALUE klass;
ID id;
{ {
remove_method(mod, rb_to_id(name)); VALUE origin;
return mod; 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 static VALUE
rb_mod_undef_method(mod, name) rb_mod_undef_method(mod, name)
VALUE mod, name; VALUE mod, name;
{ {
ID id = rb_to_id(name); rb_undef(mod, rb_to_id(name));
rb_add_method(mod, id, 0, NOEX_PUBLIC);
rb_clear_cache_by_id(id);
return mod; 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 static VALUE
rb_mod_alias_method(mod, newname, oldname) rb_mod_alias_method(mod, newname, oldname)
VALUE mod, newname, oldname; VALUE mod, newname, oldname;
{ {
ID id = rb_to_id(newname); rb_alias(mod, rb_to_id(newname), rb_to_id(oldname));
rb_alias(mod, id, rb_to_id(oldname));
rb_clear_cache_by_id(id);
return mod; return mod;
} }
@ -1628,7 +1664,7 @@ is_defined(self, node, buf)
break; break;
case NODE_CVAR: 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"; return "constant";
} }
break; break;
@ -1644,7 +1680,7 @@ is_defined(self, node, buf)
switch (TYPE(val)) { switch (TYPE(val)) {
case T_CLASS: case T_CLASS:
case T_MODULE: case T_MODULE:
if (rb_shvar_defined_at(val, node->nd_mid)) if (rb_const_defined_at(val, node->nd_mid))
return "constant"; return "constant";
default: default:
if (rb_method_boundp(val, node->nd_mid, 1)) { 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"); rb_raise(rb_eTypeError, "no class/module to define constant");
} }
result = rb_eval(self, node->nd_value); 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; break;
case NODE_CDECL: case NODE_CDECL:
@ -2443,7 +2479,7 @@ rb_eval(self, node)
rb_raise(rb_eTypeError, "no class/module to define constant"); rb_raise(rb_eTypeError, "no class/module to define constant");
} }
result = rb_eval(self, node->nd_value); 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; break;
case NODE_LVAR: case NODE_LVAR:
@ -2466,7 +2502,7 @@ rb_eval(self, node)
break; break;
case NODE_CVAR: 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; break;
case NODE_BLOCK_ARG: case NODE_BLOCK_ARG:
@ -2493,12 +2529,12 @@ rb_eval(self, node)
default: default:
return rb_funcall(klass, node->nd_mid, 0, 0); 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; break;
case NODE_COLON3: case NODE_COLON3:
result = rb_shvar_get(rb_cObject, node->nd_mid); result = rb_const_get(rb_cObject, node->nd_mid);
break; break;
case NODE_NTH_REF: case NODE_NTH_REF:
@ -2655,14 +2691,9 @@ rb_eval(self, node)
} }
body = search_method(ruby_class, node->nd_mid, &origin); body = search_method(ruby_class, node->nd_mid, &origin);
if (body){ if (body){
if (origin == ruby_class) {
if (safe_level >= 4) {
rb_raise(rb_eSecurityError, "re-defining method prohibited");
}
if (RTEST(ruby_verbose)) { if (RTEST(ruby_verbose)) {
rb_warning("discarding old %s", rb_id2name(node->nd_mid)); rb_warning("discarding old %s", rb_id2name(node->nd_mid));
} }
}
rb_clear_cache_by_id(node->nd_mid); rb_clear_cache_by_id(node->nd_mid);
} }
@ -2711,7 +2742,7 @@ rb_eval(self, node)
rb_class2name(CLASS_OF(recv))); 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"); rb_raise(rb_eSecurityError, "can't define singleton method");
} }
klass = rb_singleton_class(recv); klass = rb_singleton_class(recv);
@ -2733,40 +2764,14 @@ rb_eval(self, node)
break; break;
case NODE_UNDEF: case NODE_UNDEF:
{
VALUE origin;
NODE *body;
if (NIL_P(ruby_class)) { if (NIL_P(ruby_class)) {
rb_raise(rb_eTypeError, "no class to undef method"); rb_raise(rb_eTypeError, "no class to undef method");
} }
if (ruby_class == rb_cObject) { if (ruby_class == rb_cObject) {
rb_secure(4); rb_secure(4);
} }
body = search_method(ruby_class, node->nd_mid, &origin); rb_undef(ruby_class, node->nd_mid);
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; result = Qnil;
}
break; break;
case NODE_ALIAS: case NODE_ALIAS:
@ -2799,12 +2804,16 @@ rb_eval(self, node)
} }
klass = 0; klass = 0;
if (rb_shvar_defined_at(ruby_class, node->nd_cname) && if ((ruby_class == rb_cObject || ruby_class == ruby_wrapper) &&
(ruby_class != rb_cObject || !rb_autoload_defined(node->nd_cname))) { rb_autoload_defined(node->nd_cname)) {
klass = rb_shvar_get(ruby_class, node->nd_cname); rb_autoload_load(node->nd_cname);
} }
if (ruby_wrapper && rb_shvar_defined_at(rb_cObject, node->nd_cname)) { if (rb_const_defined_at(ruby_class, node->nd_cname)) {
klass = rb_shvar_get(rb_cObject, node->nd_cname); klass = rb_const_get(ruby_class, 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 (klass) {
if (TYPE(klass) != T_CLASS) { if (TYPE(klass) != T_CLASS) {
@ -2832,7 +2841,7 @@ rb_eval(self, node)
else { else {
if (!super) super = rb_cObject; if (!super) super = rb_cObject;
klass = rb_define_class_id(node->nd_cname, super); 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)); rb_set_class_path(klass,ruby_class,rb_id2name(node->nd_cname));
} }
if (ruby_wrapper) { if (ruby_wrapper) {
@ -2852,13 +2861,16 @@ rb_eval(self, node)
rb_raise(rb_eTypeError, "no outer class/module"); rb_raise(rb_eTypeError, "no outer class/module");
} }
module = 0; module = 0;
if (rb_shvar_defined_at(ruby_class, node->nd_cname) && if ((ruby_class == rb_cObject || ruby_class == ruby_wrapper) &&
(ruby_class != rb_cObject || rb_autoload_defined(node->nd_cname)) {
!rb_autoload_defined(node->nd_cname))) { rb_autoload_load(node->nd_cname);
module = rb_shvar_get(ruby_class, node->nd_cname);
} }
if (ruby_wrapper && rb_shvar_defined_at(rb_cObject, node->nd_cname)) { if (rb_const_defined_at(ruby_class, node->nd_cname)) {
module = rb_shvar_get(rb_cObject, 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 (module) {
if (TYPE(module) != T_MODULE) { if (TYPE(module) != T_MODULE) {
@ -2871,7 +2883,7 @@ rb_eval(self, node)
} }
else { else {
module = rb_define_module_id(node->nd_cname); 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)); rb_set_class_path(module,ruby_class,rb_id2name(node->nd_cname));
} }
if (ruby_wrapper) { if (ruby_wrapper) {
@ -2892,10 +2904,13 @@ rb_eval(self, node)
rb_raise(rb_eTypeError, "no virtual class for %s", rb_raise(rb_eTypeError, "no virtual class for %s",
rb_class2name(CLASS_OF(klass))); 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)) { if (FL_TEST(CLASS_OF(klass), FL_SINGLETON)) {
rb_clear_cache(); rb_clear_cache();
} }
klass = rb_singleton_class(klass); klass = rb_singleton_class(klass);
if (ruby_wrapper) { if (ruby_wrapper) {
rb_extend_object(klass, ruby_wrapper); rb_extend_object(klass, ruby_wrapper);
rb_include_module(klass, ruby_wrapper); rb_include_module(klass, ruby_wrapper);
@ -3414,11 +3429,11 @@ assign(self, lhs, val, check)
break; break;
case NODE_CASGN: 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; break;
case NODE_CDECL: case NODE_CDECL:
rb_shvar_set(ruby_class, lhs->nd_vid, val); rb_const_set(ruby_class, lhs->nd_vid, val);
break; break;
case NODE_MASGN: case NODE_MASGN:
@ -4557,7 +4572,7 @@ static VALUE
yield_under(under, self) yield_under(under, self)
VALUE 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"); rb_raise(rb_eSecurityError, "Insecure: can't eval");
return exec_under(yield_under_i, under, self); return exec_under(yield_under_i, under, self);
} }
@ -4649,7 +4664,6 @@ static char*
find_file(file) find_file(file)
char *file; char *file;
{ {
extern VALUE rb_load_path;
volatile VALUE vpath; volatile VALUE vpath;
char *path; char *path;
@ -4692,7 +4706,7 @@ find_file(file)
vpath = rb_ary_join(vpath, rb_str_new2(PATH_SEP)); vpath = rb_ary_join(vpath, rb_str_new2(PATH_SEP));
path = STR2CSTR(vpath); path = STR2CSTR(vpath);
if (safe_level >= 2 && !rb_path_check(path)) { 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 { else {
@ -4868,8 +4882,8 @@ rb_f_require(obj, fname)
char *ext, *file, *feature, *buf; /* OK */ char *ext, *file, *feature, *buf; /* OK */
volatile VALUE load; volatile VALUE load;
int state; int state;
volatile int safe = safe_level;
rb_secure(4);
Check_SafeStr(fname); Check_SafeStr(fname);
if (rb_provided(RSTRING(fname)->ptr)) if (rb_provided(RSTRING(fname)->ptr))
return Qfalse; return Qfalse;
@ -4936,6 +4950,7 @@ rb_f_require(obj, fname)
return Qtrue; return Qtrue;
load_rb: load_rb:
safe_level = 0;
if (rb_thread_loading(feature)) return Qfalse; if (rb_thread_loading(feature)) return Qfalse;
rb_provide(feature); rb_provide(feature);
@ -4945,6 +4960,7 @@ rb_f_require(obj, fname)
} }
POP_TAG(); POP_TAG();
rb_thread_loading_done(feature); rb_thread_loading_done(feature);
safe_level = safe;
if (state) JUMP_TAG(state); if (state) JUMP_TAG(state);
return Qtrue; return Qtrue;
@ -5399,9 +5415,7 @@ Init_eval()
rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2); 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, "nesting", rb_mod_nesting, 0);
rb_define_singleton_method(rb_cModule, "shared_variables", rb_mod_s_shvars, 0); rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, 0);
/* to be removed at 1.6 */
rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_shvars, 0);
rb_define_singleton_method(ruby_top_self, "include", top_include, -1); rb_define_singleton_method(ruby_top_self, "include", top_include, -1);
rb_define_singleton_method(ruby_top_self, "public", top_public, -1); rb_define_singleton_method(ruby_top_self, "public", top_public, -1);
@ -5617,7 +5631,7 @@ static void
proc_save_safe_level(data) proc_save_safe_level(data)
VALUE data; VALUE data;
{ {
if (FL_TEST(data, FL_TAINT)) { if (OBJ_TAINTED(data)) {
switch (safe_level) { switch (safe_level) {
case 3: case 3:
FL_SET(data, PROC_T3); FL_SET(data, PROC_T3);
@ -5636,7 +5650,7 @@ static void
proc_set_safe_level(data) proc_set_safe_level(data)
VALUE data; VALUE data;
{ {
if (FL_TEST(data, FL_TAINT)) { if (OBJ_TAINTED(data)) {
switch (RBASIC(data)->flags & PROC_TMASK) { switch (RBASIC(data)->flags & PROC_TMASK) {
case PROC_T3: case PROC_T3:
safe_level = 3; safe_level = 3;
@ -5923,8 +5937,8 @@ rb_obj_method(obj, vid)
data->body = body; data->body = body;
data->oklass = CLASS_OF(obj); data->oklass = CLASS_OF(obj);
data->oid = rb_to_id(vid); data->oid = rb_to_id(vid);
if (FL_TEST(obj, FL_TAINT)) { if (OBJ_TAINTED(obj)) {
FL_SET(method, FL_TAINT); OBJ_TAINT(method);
} }
return method; return method;
@ -5944,8 +5958,8 @@ method_call(argc, argv, method)
Data_Get_Struct(method, struct METHOD, data); Data_Get_Struct(method, struct METHOD, data);
PUSH_ITER(rb_iterator_p()?ITER_PRE:ITER_NOT); PUSH_ITER(rb_iterator_p()?ITER_PRE:ITER_NOT);
PUSH_TAG(PROT_NONE); PUSH_TAG(PROT_NONE);
if (FL_TEST(data->recv, FL_TAINT) || FL_TEST(method, FL_TAINT)) { if (OBJ_TAINTED(data->recv) || OBJ_TAINTED(method)) {
FL_SET(method, FL_TAINT); OBJ_TAINT(method);
if (safe_level < 4) safe_level = 4; if (safe_level < 4) safe_level = 4;
} }
if ((state = EXEC_TAG()) == 0) { if ((state = EXEC_TAG()) == 0) {
@ -6140,6 +6154,7 @@ struct thread {
thread_t join; thread_t join;
int abort; int abort;
int priority;
st_table *locals; st_table *locals;
@ -6501,8 +6516,8 @@ rb_thread_schedule()
FOREACH_THREAD_FROM(curr, th) { FOREACH_THREAD_FROM(curr, th) {
if (th->status != THREAD_STOPPED && th->status != THREAD_KILLED) { if (th->status != THREAD_STOPPED && th->status != THREAD_KILLED) {
if (!next || next->priority < th->priority)
next = th; next = th;
break;
} }
} }
END_FOREACH_FROM(curr, th); END_FOREACH_FROM(curr, th);
@ -6514,7 +6529,8 @@ rb_thread_schedule()
th->wait_for &= ~WAIT_JOIN; th->wait_for &= ~WAIT_JOIN;
th->status = THREAD_RUNNABLE; th->status = THREAD_RUNNABLE;
num_waiting_on_join--; num_waiting_on_join--;
if (!next) next = th; if (!next || next->priority < th->priority)
next = th;
} }
} }
END_FOREACH_FROM(curr, th); END_FOREACH_FROM(curr, th);
@ -6600,7 +6616,8 @@ rb_thread_schedule()
th->fd = 0; th->fd = 0;
th->wait_for &= ~WAIT_FD; th->wait_for &= ~WAIT_FD;
num_waiting_on_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); END_FOREACH_FROM(curr, th);
@ -6972,6 +6989,31 @@ rb_thread_sleep_forever()
rb_thread_schedule(); 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 int thread_abort;
static VALUE static VALUE
@ -6984,6 +7026,7 @@ static VALUE
rb_thread_s_abort_exc_set(self, val) rb_thread_s_abort_exc_set(self, val)
VALUE self, val; VALUE self, val;
{ {
rb_secure(4);
thread_abort = RTEST(val); thread_abort = RTEST(val);
return val; return val;
} }
@ -7003,6 +7046,7 @@ rb_thread_abort_exc_set(thread, val)
{ {
thread_t th = rb_thread_check(thread); thread_t th = rb_thread_check(thread);
rb_secure(4);
th->abort = RTEST(val); th->abort = RTEST(val);
return val; return val;
} }
@ -7035,6 +7079,7 @@ rb_thread_abort_exc_set(thread, val)
th->last_line = 0;\ th->last_line = 0;\
th->last_match = 0;\ th->last_match = 0;\
th->abort = 0;\ th->abort = 0;\
th->priority = 0;\
th->locals = 0;\ th->locals = 0;\
} while(0) } while(0)
@ -7052,6 +7097,7 @@ rb_thread_alloc(klass)
curr_thread->next->prev = th; curr_thread->next->prev = th;
th->next = curr_thread->next; th->next = curr_thread->next;
curr_thread->next = th; curr_thread->next = th;
th->priority = curr_thread->priority;
} }
else { else {
curr_thread = th->prev = th->next = th; curr_thread = th->prev = th->next = th;
@ -7278,13 +7324,13 @@ rb_thread_cleanup()
int rb_thread_critical; int rb_thread_critical;
static VALUE static VALUE
rb_thread_get_critical() rb_thread_critical_get()
{ {
return rb_thread_critical?Qtrue:Qfalse; return rb_thread_critical?Qtrue:Qfalse;
} }
static VALUE static VALUE
rb_thread_set_critical(obj, val) rb_thread_critical_set(obj, val)
VALUE obj, val; VALUE obj, val;
{ {
rb_thread_critical = RTEST(val); rb_thread_critical = RTEST(val);
@ -7417,6 +7463,9 @@ rb_thread_local_aref(thread, id)
VALUE val; VALUE val;
th = rb_thread_check(thread); 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 (!th->locals) return Qnil;
if (st_lookup(th->locals, id, &val)) { if (st_lookup(th->locals, id, &val)) {
return val; return val;
@ -7439,8 +7488,9 @@ rb_thread_local_aset(thread, id, val)
{ {
thread_t th = rb_thread_check(thread); thread_t th = rb_thread_check(thread);
if (safe_level >= 4 && !FL_TEST(thread, FL_TAINT)) if (safe_level >= 4 && th != curr_thread) {
rb_raise(rb_eSecurityError, "Insecure: can't modify thread values"); rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals");
}
if (!th->locals) { if (!th->locals) {
th->locals = st_init_numtable(); 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, "current", rb_thread_current, 0);
rb_define_singleton_method(rb_cThread, "main", rb_thread_main, 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_critical_get, 0);
rb_define_singleton_method(rb_cThread, "critical=", rb_thread_set_critical, 1); 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, 0);
rb_define_singleton_method(rb_cThread, "abort_on_exception=", rb_thread_s_abort_exc_set, 1); 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, 0);
rb_define_method(rb_cThread, "abort_on_exception=", rb_thread_abort_exc_set, 1); 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_aref, 1);
rb_define_method(rb_cThread, "[]=", rb_thread_aset, 2); rb_define_method(rb_cThread, "[]=", rb_thread_aset, 2);
rb_define_method(rb_cThread, "key?", rb_thread_key_p, 1); rb_define_method(rb_cThread, "key?", rb_thread_key_p, 1);

View file

@ -315,19 +315,12 @@ fdbm_store(obj, keystr, valstr)
struct dbmdata *dbmp; struct dbmdata *dbmp;
DBM *dbm; DBM *dbm;
if (valstr == Qnil) {
fdbm_delete(obj, keystr);
return Qnil;
}
rb_secure(4); rb_secure(4);
keystr = rb_obj_as_string(keystr); keystr = rb_obj_as_string(keystr);
key.dptr = RSTRING(keystr)->ptr; key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len; key.dsize = RSTRING(keystr)->len;
if (NIL_P(valstr)) return fdbm_delete(obj, keystr);
valstr = rb_obj_as_string(valstr); valstr = rb_obj_as_string(valstr);
val.dptr = RSTRING(valstr)->ptr; val.dptr = RSTRING(valstr)->ptr;
val.dsize = RSTRING(valstr)->len; val.dsize = RSTRING(valstr)->len;

View file

@ -169,7 +169,7 @@ fgdbm_delete(obj, keystr)
if (gdbm_delete(dbm, key)) { if (gdbm_delete(dbm, key)) {
dbmp->di_size = -1; dbmp->di_size = -1;
rb_raise(rb_eRuntimeError, "dbm_delete failed"); rb_raise(rb_eRuntimeError, "gdbm_delete failed");
} }
else if (dbmp->di_size >= 0) { else if (dbmp->di_size >= 0) {
dbmp->di_size--; dbmp->di_size--;
@ -218,7 +218,7 @@ fgdbm_delete_if(obj)
valstr = rb_tainted_str_new(val.dptr, val.dsize); valstr = rb_tainted_str_new(val.dptr, val.dsize);
if (RTEST(rb_yield(rb_assoc_new(keystr, valstr)))) { if (RTEST(rb_yield(rb_assoc_new(keystr, valstr)))) {
if (gdbm_delete(dbm, key)) { 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) { for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) {
nextkey = gdbm_nextkey(dbm, key); nextkey = gdbm_nextkey(dbm, key);
if (gdbm_delete(dbm, key)) { if (gdbm_delete(dbm, key)) {
rb_raise(rb_eRuntimeError, "dbm_delete failed"); rb_raise(rb_eRuntimeError, "gdbm_delete failed");
} }
} }
return obj; return obj;
@ -313,19 +313,12 @@ fgdbm_store(obj, keystr, valstr)
struct dbmdata *dbmp; struct dbmdata *dbmp;
GDBM_FILE dbm; GDBM_FILE dbm;
if (valstr == Qnil) {
fgdbm_delete(obj, keystr);
return Qnil;
}
rb_secure(4); rb_secure(4);
keystr = rb_obj_as_string(keystr); keystr = rb_obj_as_string(keystr);
key.dptr = RSTRING(keystr)->ptr; key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len; key.dsize = RSTRING(keystr)->len;
if (NIL_P(valstr)) return fgdbm_delete(obj, keystr);
valstr = rb_obj_as_string(valstr); valstr = rb_obj_as_string(valstr);
val.dptr = RSTRING(valstr)->ptr; val.dptr = RSTRING(valstr)->ptr;
val.dsize = RSTRING(valstr)->len; val.dsize = RSTRING(valstr)->len;
@ -335,7 +328,7 @@ fgdbm_store(obj, keystr, valstr)
dbm = dbmp->di_dbm; dbm = dbmp->di_dbm;
if (gdbm_store(dbm, key, val, GDBM_REPLACE)) { if (gdbm_store(dbm, key, val, GDBM_REPLACE)) {
if (errno == EPERM) rb_sys_fail(0); if (errno == EPERM) rb_sys_fail(0);
rb_raise(rb_eRuntimeError, "dbm_store failed"); rb_raise(rb_eRuntimeError, "gdbm_store failed");
} }
return valstr; return valstr;

View file

@ -115,7 +115,6 @@ sock_new(class, fd)
NEWOBJ(sock, struct RFile); NEWOBJ(sock, struct RFile);
OBJSETUP(sock, class, T_FILE); OBJSETUP(sock, class, T_FILE);
rb_secure(4);
MakeOpenFile(sock, fp); MakeOpenFile(sock, fp);
fp->f = rb_fdopen(fd, "r"); fp->f = rb_fdopen(fd, "r");
#ifdef NT #ifdef NT
@ -140,7 +139,9 @@ bsock_shutdown(argc, argv, sock)
int how; int how;
OpenFile *fptr; 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); rb_scan_args(argc, argv, "01", &howto);
if (howto == Qnil) if (howto == Qnil)
how = 2; how = 2;
@ -163,7 +164,9 @@ bsock_close_read(sock)
{ {
OpenFile *fptr; 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); GetOpenFile(sock, fptr);
shutdown(fileno(fptr->f), 0); shutdown(fileno(fptr->f), 0);
if (fptr->f2 == 0) { if (fptr->f2 == 0) {
@ -188,7 +191,9 @@ bsock_close_write(sock)
{ {
OpenFile *fptr; 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); GetOpenFile(sock, fptr);
if (fptr->f2 == 0) { if (fptr->f2 == 0) {
return rb_io_close(sock); return rb_io_close(sock);
@ -215,7 +220,6 @@ bsock_setsockopt(sock, lev, optname, val)
char *v; char *v;
int vlen; int vlen;
rb_secure(2);
level = NUM2INT(lev); level = NUM2INT(lev);
option = NUM2INT(optname); option = NUM2INT(optname);
switch (TYPE(val)) { switch (TYPE(val)) {
@ -794,6 +798,9 @@ socks_s_close(sock)
{ {
OpenFile *fptr; OpenFile *fptr;
if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
rb_raise(rb_eSecurityError, "Insecure: can't close socket");
}
GetOpenFile(sock, fptr); GetOpenFile(sock, fptr);
shutdown(fileno(fptr->f), 2); shutdown(fileno(fptr->f), 2);
shutdown(fileno(fptr->f2), 2); shutdown(fileno(fptr->f2), 2);

View file

@ -2150,7 +2150,7 @@ class TkListbox<TkTextWin
def nearest(y) def nearest(y)
tk_send('nearest', y).to_i tk_send('nearest', y).to_i
end end
def size(y) def size
tk_send('size').to_i tk_send('size').to_i
end end
def selection_anchor(index) def selection_anchor(index)
@ -2159,8 +2159,8 @@ class TkListbox<TkTextWin
def selection_clear(first, last=None) def selection_clear(first, last=None)
tk_send 'selection', 'clear', first, last tk_send 'selection', 'clear', first, last
end end
def selection_includes def selection_includes(index)
bool(tk_send('selection', 'includes')) bool(tk_send('selection', 'includes', index))
end end
def selection_set(first, last=None) def selection_set(first, last=None)
tk_send 'selection', 'set', first, last tk_send 'selection', 'set', first, last

21
file.c
View file

@ -102,7 +102,7 @@ rb_file_path(obj)
OpenFile *fptr; OpenFile *fptr;
GetOpenFile(obj, fptr); GetOpenFile(obj, fptr);
if (fptr->path == NULL) return Qnil; if (!fptr->path) return Qnil;
return rb_str_new2(fptr->path); return rb_str_new2(fptr->path);
} }
@ -261,7 +261,7 @@ rb_stat(file, st)
if (TYPE(file) == T_FILE) { if (TYPE(file) == T_FILE) {
OpenFile *fptr; OpenFile *fptr;
rb_secure(4); rb_secure(2);
GetOpenFile(file, fptr); GetOpenFile(file, fptr);
return fstat(fileno(fptr->f), st); return fstat(fileno(fptr->f), st);
} }
@ -325,8 +325,9 @@ rb_file_lstat(obj)
OpenFile *fptr; OpenFile *fptr;
struct stat st; struct stat st;
rb_secure(4); rb_secure(2);
GetOpenFile(obj, fptr); GetOpenFile(obj, fptr);
if (!fptr->path) return Qnil;
if (lstat(fptr->path, &st) == -1) { if (lstat(fptr->path, &st) == -1) {
rb_sys_fail(fptr->path); rb_sys_fail(fptr->path);
} }
@ -463,8 +464,8 @@ test_l(obj, fname)
Check_SafeStr(fname); Check_SafeStr(fname);
if (lstat(RSTRING(fname)->ptr, &st) < 0) return Qfalse; if (lstat(RSTRING(fname)->ptr, &st) < 0) return Qfalse;
if (S_ISLNK(st.st_mode)) return Qtrue; if (S_ISLNK(st.st_mode)) return Qtrue;
#endif #endif
return Qfalse; return Qfalse;
} }
@ -896,11 +897,12 @@ rb_file_chmod(obj, vmode)
OpenFile *fptr; OpenFile *fptr;
int mode; int mode;
rb_secure(4); rb_secure(2);
mode = NUM2INT(vmode); mode = NUM2INT(vmode);
GetOpenFile(obj, fptr); GetOpenFile(obj, fptr);
#if defined(DJGPP) || defined(NT) || defined(USE_CWGUSI) || defined(__BEOS__) || defined(__EMX__) #if defined(DJGPP) || defined(NT) || defined(USE_CWGUSI) || defined(__BEOS__) || defined(__EMX__)
if (!fptr->path) return Qnil;
if (chmod(fptr->path, mode) == -1) if (chmod(fptr->path, mode) == -1)
rb_sys_fail(fptr->path); rb_sys_fail(fptr->path);
#else #else
@ -957,9 +959,10 @@ rb_file_chown(obj, owner, group)
{ {
OpenFile *fptr; OpenFile *fptr;
rb_secure(4); rb_secure(2);
GetOpenFile(obj, fptr); GetOpenFile(obj, fptr);
#if defined(DJGPP) || defined(__CYGWIN32__) || defined(NT) || defined(USE_CWGUSI) || defined(__EMX__) #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) if (chown(fptr->path, NUM2INT(owner), NUM2INT(group)) == -1)
rb_sys_fail(fptr->path); rb_sys_fail(fptr->path);
#else #else
@ -1147,7 +1150,7 @@ rb_file_s_umask(argc, argv)
#else #else
int omask = 0; int omask = 0;
rb_secure(4); rb_secure(2);
if (argc == 0) { if (argc == 0) {
omask = umask(0); omask = umask(0);
umask(omask); umask(omask);
@ -1426,7 +1429,7 @@ rb_file_truncate(obj, len)
{ {
OpenFile *fptr; OpenFile *fptr;
rb_secure(4); rb_secure(2);
GetOpenFile(obj, fptr); GetOpenFile(obj, fptr);
if (!(fptr->mode & FMODE_WRITABLE)) { if (!(fptr->mode & FMODE_WRITABLE)) {
rb_raise(rb_eIOError, "not opened for writing"); rb_raise(rb_eIOError, "not opened for writing");
@ -1494,7 +1497,7 @@ rb_file_flock(obj, operation)
#else #else
OpenFile *fptr; OpenFile *fptr;
rb_secure(4); rb_secure(2);
GetOpenFile(obj, fptr); GetOpenFile(obj, fptr);
if (flock(fileno(fptr->f), NUM2INT(operation)) < 0) { if (flock(fileno(fptr->f), NUM2INT(operation)) < 0) {

30
gc.c
View file

@ -51,6 +51,17 @@ static unsigned long alloc_objects = 0;
static int malloc_called = 0; static int malloc_called = 0;
static int free_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 #ifndef xmalloc
void * void *
@ -72,8 +83,12 @@ xmalloc(size)
if (!mem) { if (!mem) {
rb_gc(); rb_gc();
mem = malloc(size); mem = malloc(size);
if (!mem) if (!mem) {
rb_fatal("failed to allocate memory"); if (size >= 10 * 1024 * 1024) {
rb_raise(rb_eNoMemError, "try to allocate too big memory");
}
mem_error("failed to allocate memory");
}
} }
return mem; return mem;
@ -109,7 +124,10 @@ xrealloc(ptr, size)
rb_gc(); rb_gc();
mem = realloc(ptr, size); mem = realloc(ptr, size);
if (!mem) 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; return mem;
@ -244,11 +262,11 @@ add_heap()
heaps = (heaps_used>0)? heaps = (heaps_used>0)?
(RVALUE**)realloc(heaps, heaps_length*sizeof(RVALUE*)): (RVALUE**)realloc(heaps, heaps_length*sizeof(RVALUE*)):
(RVALUE**)malloc(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); 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; pend = p + HEAP_SLOTS;
if (lomem == 0 || lomem > p) lomem = p; if (lomem == 0 || lomem > p) lomem = p;
if (himem < pend) himem = pend; if (himem < pend) himem = pend;
@ -370,7 +388,7 @@ rb_mark_tbl(tbl)
static int static int
mark_hashentry(key, value) mark_hashentry(key, value)
ID key; VALUE key;
VALUE value; VALUE value;
{ {
rb_gc_mark(key); rb_gc_mark(key);

5
hash.c
View file

@ -35,7 +35,7 @@ rb_hash_modify(hash)
{ {
if (FL_TEST(hash, HASH_FREEZE)) if (FL_TEST(hash, HASH_FREEZE))
rb_raise(rb_eTypeError, "can't modify frozen hash"); 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"); rb_raise(rb_eSecurityError, "Insecure: can't modify hash");
} }
@ -43,6 +43,9 @@ VALUE
rb_hash_freeze(hash) rb_hash_freeze(hash)
VALUE 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); FL_SET(hash, HASH_FREEZE);
return hash; return hash;
} }

View file

@ -221,7 +221,7 @@ int yyparse _((void));
ID rb_id_attrset _((ID)); ID rb_id_attrset _((ID));
void rb_parser_append_print _((void)); void rb_parser_append_print _((void));
void rb_parser_while_loop _((int, int)); 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)); int rb_is_instance_id _((ID));
VALUE rb_backref_get _((void)); VALUE rb_backref_get _((void));
void rb_backref_set _((VALUE)); void rb_backref_set _((VALUE));
@ -323,17 +323,18 @@ VALUE rb_ivar_set _((VALUE, ID, VALUE));
VALUE rb_ivar_defined _((VALUE, ID)); VALUE rb_ivar_defined _((VALUE, ID));
VALUE rb_obj_instance_variables _((VALUE)); VALUE rb_obj_instance_variables _((VALUE));
VALUE rb_obj_remove_instance_variable _((VALUE, VALUE)); VALUE rb_obj_remove_instance_variable _((VALUE, VALUE));
VALUE rb_mod_shvar_at _((VALUE, VALUE)); VALUE rb_mod_const_at _((VALUE, VALUE));
VALUE rb_mod_shvars _((VALUE)); VALUE rb_mod_constants _((VALUE));
VALUE rb_mod_shvar_of _((VALUE, VALUE)); VALUE rb_mod_const_of _((VALUE, VALUE));
VALUE rb_mod_remove_shvar _((VALUE, VALUE)); VALUE rb_mod_remove_const _((VALUE, VALUE));
int rb_shvar_defined_at _((VALUE, ID)); int rb_const_defined_at _((VALUE, ID));
int rb_autoload_defined _((ID)); int rb_autoload_defined _((ID));
int rb_shvar_defined _((VALUE, ID)); int rb_const_defined _((VALUE, ID));
VALUE rb_shvar_get _((VALUE, ID)); VALUE rb_const_get _((VALUE, ID));
VALUE rb_shvar_get_at _((VALUE, ID)); VALUE rb_const_get_at _((VALUE, ID));
void rb_shvar_set _((VALUE, ID, VALUE)); void rb_const_set _((VALUE, ID, VALUE));
VALUE rb_mod_shared_variables _((VALUE)); VALUE rb_mod_constants _((VALUE));
void rb_autoload_load _((ID));
/* version.c */ /* version.c */
void ruby_show_version _((void)); void ruby_show_version _((void));
void ruby_show_copyright _((void)); void ruby_show_copyright _((void));

20
io.c
View file

@ -969,7 +969,9 @@ static VALUE
rb_io_close_method(io) rb_io_close_method(io)
VALUE 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); rb_io_close(io);
return Qnil; return Qnil;
} }
@ -991,7 +993,9 @@ rb_io_close_read(io)
OpenFile *fptr; OpenFile *fptr;
int n; int n;
rb_secure(4); if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) {
rb_raise(rb_eSecurityError, "Insecure: can't close");
}
GetOpenFile(io, fptr); GetOpenFile(io, fptr);
if (fptr->f2 == 0 && (fptr->mode & FMODE_WRITABLE)) { if (fptr->f2 == 0 && (fptr->mode & FMODE_WRITABLE)) {
rb_raise(rb_eIOError, "closing non-duplex IO for reading"); rb_raise(rb_eIOError, "closing non-duplex IO for reading");
@ -1015,7 +1019,9 @@ rb_io_close_write(io)
OpenFile *fptr; OpenFile *fptr;
int n; int n;
rb_secure(4); if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) {
rb_raise(rb_eSecurityError, "Insecure: can't close");
}
GetOpenFile(io, fptr); GetOpenFile(io, fptr);
if (fptr->f2 == 0 && (fptr->mode & FMODE_READABLE)) { if (fptr->f2 == 0 && (fptr->mode & FMODE_READABLE)) {
rb_raise(rb_eIOError, "closing non-duplex IO for writing"); rb_raise(rb_eIOError, "closing non-duplex IO for writing");
@ -1685,9 +1691,11 @@ rb_io_reopen(io, nfile)
char *mode; char *mode;
int fd; int fd;
rb_secure(4);
GetOpenFile(io, fptr);
nfile = rb_io_get_io(nfile); 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); GetOpenFile(nfile, orig);
if (fptr == orig) return io; if (fptr == orig) return io;
@ -3070,6 +3078,8 @@ argf_eof()
{ {
if (init_p == 0 && !next_argv()) if (init_p == 0 && !next_argv())
return Qtrue; return Qtrue;
if (next_p == -1)
return Qtrue;
if (TYPE(current_file) != T_FILE) { if (TYPE(current_file) != T_FILE) {
return argf_forward(); return argf_forward();
} }

View file

@ -203,7 +203,12 @@ The variable ruby-indent-level controls the amount of indentation.
(looking-at "[\\[({]") (looking-at "[\\[({]")
(and (not modifier) (looking-at "[!?]")) (and (not modifier) (looking-at "[!?]"))
(and (looking-at ruby-symbol-re) (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)) (if (and (not modifier) (bolp))
t t
(if (or (looking-at ruby-block-beg-re) (if (or (looking-at ruby-block-beg-re)

View file

@ -283,6 +283,7 @@ VALUE
rb_obj_taint(obj) rb_obj_taint(obj)
VALUE obj; VALUE obj;
{ {
rb_secure(4);
OBJ_TAINT(obj); OBJ_TAINT(obj);
return obj; return obj;
} }
@ -688,25 +689,25 @@ rb_mod_attr_accessor(argc, argv, klass)
} }
static VALUE static VALUE
rb_mod_shvar_get(mod, name) rb_mod_const_get(mod, name)
VALUE 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 static VALUE
rb_mod_shvar_set(mod, name, value) rb_mod_const_set(mod, name, value)
VALUE 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; return value;
} }
static VALUE static VALUE
rb_mod_shvar_defined(mod, name) rb_mod_const_defined(mod, name)
VALUE 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 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, "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, "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, "constants", rb_mod_constants, 0);
rb_define_method(rb_cModule, "shared_variable_get", rb_mod_shvar_get, 1); rb_define_method(rb_cModule, "const_get", rb_mod_const_get, 1);
rb_define_method(rb_cModule, "shared_variable_set", rb_mod_shvar_set, 2); rb_define_method(rb_cModule, "const_set", rb_mod_const_set, 2);
rb_define_method(rb_cModule, "shared_variable_defined?", rb_mod_shvar_defined, 1); rb_define_method(rb_cModule, "const_defined?", rb_mod_const_defined, 1);
rb_define_private_method(rb_cModule, "remove_shared_variable", rb_mod_remove_shvar, 1); rb_define_private_method(rb_cModule, "remove_const", rb_mod_remove_const, 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_private_method(rb_cModule, "method_added", rb_obj_dummy, 1); rb_define_private_method(rb_cModule, "method_added", rb_obj_dummy, 1);
rb_define_method(rb_cClass, "new", rb_class_new_instance, -1); rb_define_method(rb_cClass, "new", rb_class_new_instance, -1);

36
parse.y
View file

@ -26,14 +26,14 @@
#define ID_INSTANCE 0x02 #define ID_INSTANCE 0x02
#define ID_GLOBAL 0x03 #define ID_GLOBAL 0x03
#define ID_ATTRSET 0x04 #define ID_ATTRSET 0x04
#define ID_SHARED 0x05 #define ID_CONST 0x05
#define is_notop_id(id) ((id)>LAST_TOKEN) #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_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_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_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_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_begin = 0;
NODE *ruby_eval_tree = 0; NODE *ruby_eval_tree = 0;
@ -717,7 +717,7 @@ arg : lhs '=' arg
$$ = $2; $$ = $2;
} }
else { else {
$$ = call_op($2, tUPLUS, 0); $$ = call_op($2, tUPLUS, 0, 0);
} }
} }
| tUMINUS arg | tUMINUS arg
@ -729,7 +729,7 @@ arg : lhs '=' arg
$$ = $2; $$ = $2;
} }
else { else {
$$ = call_op($2, tUMINUS, 0); $$ = call_op($2, tUMINUS, 0, 0);
} }
} }
| arg '|' arg | arg '|' arg
@ -791,7 +791,7 @@ arg : lhs '=' arg
} }
| '~' arg | '~' arg
{ {
$$ = call_op($2, '~', 0); $$ = call_op($2, '~', 0, 0);
} }
| arg tLSHFT arg | arg tLSHFT arg
{ {
@ -1787,10 +1787,10 @@ yycompile(f)
int n; int n;
if (!ruby_in_eval && rb_safe_level() == 0 && 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; 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) { if (TYPE(hash) == T_HASH) {
fname = rb_str_new2(f); fname = rb_str_new2(f);
ruby_debug_lines = rb_hash_aref(hash, fname); ruby_debug_lines = rb_hash_aref(hash, fname);
@ -2880,7 +2880,7 @@ yylex()
/* binary */ /* binary */
c = nextc(); c = nextc();
if (c != '0' && c != '1') { if (c != '0' && c != '1') {
yyerror("numeric constant with no digits"); yyerror("numeric literal without digits");
} }
do { do {
if (c == '_') continue; if (c == '_') continue;
@ -3715,7 +3715,7 @@ gettable(id)
else if (is_instance_id(id)) { else if (is_instance_id(id)) {
return NEW_IVAR(id); return NEW_IVAR(id);
} }
else if (is_shared_id(id)) { else if (is_const_id(id)) {
return NEW_CVAR(id); return NEW_CVAR(id);
} }
rb_bug("invalid id for gettable"); rb_bug("invalid id for gettable");
@ -3766,10 +3766,9 @@ assignable(id, val)
else if (is_instance_id(id)) { else if (is_instance_id(id)) {
lhs = NEW_IASGN(id, val); lhs = NEW_IASGN(id, val);
} }
else if (is_shared_id(id)) { else if (is_const_id(id)) {
if (cur_mid || in_single) if (cur_mid || in_single)
lhs = NEW_CASGN(id, val); yyerror("dynamic constant assignment");
else
lhs = NEW_CDECL(id, val); lhs = NEW_CDECL(id, val);
} }
else { else {
@ -4496,7 +4495,7 @@ rb_intern(name)
id = ID_ATTRSET; id = ID_ATTRSET;
} }
else if (ISUPPER(name[0])) { else if (ISUPPER(name[0])) {
id = ID_SHARED; id = ID_CONST;
} }
else { else {
id = ID_LOCAL; id = ID_LOCAL;
@ -4548,19 +4547,12 @@ rb_id2name(id)
return 0; return 0;
} }
int
rb_is_shared_id(id)
ID id;
{
if (is_shared_id(id)) return Qtrue;
return Qfalse;
}
int int
rb_is_const_id(id) rb_is_const_id(id)
ID id; ID id;
{ {
return rb_is_shared_id(id); if (is_const_id(id)) return Qtrue;
return Qfalse;
} }
int int

View file

@ -831,6 +831,7 @@ proc_setpgid(obj, pid, pgrp)
#ifdef HAVE_SETPGID #ifdef HAVE_SETPGID
int ipid, ipgrp; int ipid, ipgrp;
rb_secure(2);
ipid = NUM2INT(pid); ipid = NUM2INT(pid);
ipgrp = NUM2INT(pgrp); ipgrp = NUM2INT(pgrp);
@ -845,8 +846,10 @@ static VALUE
proc_setsid() proc_setsid()
{ {
#ifdef HAVE_SETSID #ifdef HAVE_SETSID
int pid = setsid(); int pid;
rb_secure(2);
pid = setsid();
if (pid < 0) rb_sys_fail(0); if (pid < 0) rb_sys_fail(0);
return INT2FIX(pid); return INT2FIX(pid);
#else #else
@ -879,6 +882,7 @@ proc_setpriority(obj, which, who, prio)
#ifdef HAVE_GETPRIORITY #ifdef HAVE_GETPRIORITY
int iwhich, iwho, iprio; int iwhich, iwho, iprio;
rb_secure(2);
iwhich = NUM2INT(which); iwhich = NUM2INT(which);
iwho = NUM2INT(who); iwho = NUM2INT(who);
iprio = NUM2INT(prio); iprio = NUM2INT(prio);
@ -995,6 +999,7 @@ static VALUE
proc_setegid(obj, egid) proc_setegid(obj, egid)
VALUE obj, egid; VALUE obj, egid;
{ {
rb_secure(2);
#ifdef HAVE_SETEGID #ifdef HAVE_SETEGID
if (setegid(NUM2INT(egid)) < 0) rb_sys_fail(0); if (setegid(NUM2INT(egid)) < 0) rb_sys_fail(0);
#else #else

14
range.c
View file

@ -138,6 +138,16 @@ range_each(range)
else if (TYPE(b) == T_STRING) { else if (TYPE(b) == T_STRING) {
rb_str_upto(b, e, EXCL(range)); 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 */ else { /* generic each */
VALUE v = b; VALUE v = b;
ID succ = rb_intern("succ"); ID succ = rb_intern("succ");
@ -286,7 +296,7 @@ range_length(range)
VALUE range; VALUE range;
{ {
VALUE beg, end; VALUE beg, end;
VALUE size; long size;
beg = rb_ivar_get(range, id_beg); beg = rb_ivar_get(range, id_beg);
end = rb_ivar_get(range, id_end); end = rb_ivar_get(range, id_end);
@ -302,7 +312,7 @@ range_length(range)
return INT2NUM(NUM2LONG(end) - NUM2LONG(beg) + 1); 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); return rb_length_by_each(range);
} }
size = rb_funcall(end, '-', 1, beg); size = rb_funcall(end, '-', 1, beg);

26
re.c
View file

@ -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 int
rb_reg_search(reg, str, pos, reverse) rb_reg_search(reg, str, pos, reverse)
VALUE reg, str; VALUE reg, str;

1
re.h
View file

@ -32,6 +32,7 @@ int rb_str_cicmp _((VALUE, VALUE));
VALUE rb_reg_regcomp _((VALUE)); VALUE rb_reg_regcomp _((VALUE));
int rb_reg_search _((VALUE, VALUE, int, int)); int rb_reg_search _((VALUE, VALUE, int, int));
VALUE rb_reg_regsub _((VALUE, VALUE, struct re_registers *)); VALUE rb_reg_regsub _((VALUE, VALUE, struct re_registers *));
int rb_reg_adjust_startpos _((VALUE, VALUE, int, int));
int rb_kcode _((void)); int rb_kcode _((void));

67
regex.c
View file

@ -2922,6 +2922,47 @@ re_compile_fastmap(bufp)
FREE_AND_RETURN_VOID(stackb); FREE_AND_RETURN_VOID(stackb);
} }
/* adjust startpos value to the position between characters. */
int
re_adjust_startpos(bufp, string, size, startpos, range)
struct re_pattern_buffer *bufp;
const char *string;
int size, startpos, range;
{
/* Update the fastmap now if not correct already. */
if (!bufp->fastmap_accurate) {
re_compile_fastmap(bufp);
}
/* Adjust startpos for mbc string */
if (current_mbctype && startpos>0 && !(bufp->options&RE_OPTIMIZE_BMATCH)) {
int i = 0;
if (range > 0) {
while (i<size) {
i += mbclen(string[i]);
if (startpos <= i) {
startpos = i;
break;
}
}
}
else {
int w;
while (i<size) {
w = mbclen(string[i]);
if (startpos < i + w) {
startpos = i;
break;
}
i += w;
}
}
}
return startpos;
}
/* Using the compiled pattern in BUFP->buffer, first tries to match /* Using the compiled pattern in BUFP->buffer, first tries to match
STRING, starting first at index STARTPOS, then at STARTPOS + 1, and STRING, starting first at index STARTPOS, then at STARTPOS + 1, and
@ -2954,32 +2995,6 @@ re_search(bufp, string, size, startpos, range, regs)
re_compile_fastmap(bufp); re_compile_fastmap(bufp);
} }
/* Adjust startpos for mbc string */
if (current_mbctype && startpos>0 && !(bufp->options&RE_OPTIMIZE_BMATCH)) {
int i = 0;
if (range > 0) {
while (i<size) {
i += mbclen(string[i]);
if (startpos <= i) {
startpos = i;
break;
}
}
}
else {
int w;
while (i<size) {
w = mbclen(string[i]);
if (startpos < i + w) {
startpos = i;
break;
}
i += w;
}
}
}
/* If the search isn't to be a backwards one, don't waste time in a /* If the search isn't to be a backwards one, don't waste time in a
search for a pattern that must be anchored. */ search for a pattern that must be anchored. */

View file

@ -28,6 +28,7 @@
/* symbol mangling for ruby */ /* symbol mangling for ruby */
#ifdef RUBY #ifdef RUBY
# define re_adjust_startpos ruby_re_adjust_startpos
# define re_compile_fastmap ruby_re_compile_fastmap # define re_compile_fastmap ruby_re_compile_fastmap
# define re_compile_pattern ruby_re_compile_pattern # define re_compile_pattern ruby_re_compile_pattern
# define re_copy_registers ruby_re_copy_registers # 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 *); extern char *re_compile_pattern (const char *, int, struct re_pattern_buffer *);
void re_free_pattern (struct re_pattern_buffer *); void re_free_pattern (struct re_pattern_buffer *);
/* Is this really advertised? */ /* 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 void re_compile_fastmap (struct re_pattern_buffer *);
extern int re_search (struct re_pattern_buffer *, const char*, int, int, int, extern int re_search (struct re_pattern_buffer *, const char*, int, int, int,
struct re_registers *); struct re_registers *);
@ -206,6 +208,7 @@ extern int re_exec (const char *);
extern char *re_compile_pattern (); extern char *re_compile_pattern ();
void re_free_regexp (); void re_free_regexp ();
/* Is this really advertised? */ /* Is this really advertised? */
extern int re_adjust_startpos ();
extern void re_compile_fastmap (); extern void re_compile_fastmap ();
extern int re_search (); extern int re_search ();
extern int re_match (); extern int re_match ();

15
ruby.h
View file

@ -89,7 +89,7 @@ extern "C" {
---->> ruby requires sizeof(void*) == sizeof(long) to be compiled. <<---- ---->> ruby requires sizeof(void*) == sizeof(long) to be compiled. <<----
#endif #endif
typedef unsigned long VALUE; typedef unsigned long VALUE;
typedef unsigned int ID; typedef unsigned long ID;
#ifdef __STDC__ #ifdef __STDC__
# include <limits.h> # include <limits.h>
@ -117,6 +117,8 @@ typedef unsigned int ID;
#define INT2FIX(i) (VALUE)(((long)(i))<<1 | FIXNUM_FLAG) #define INT2FIX(i) (VALUE)(((long)(i))<<1 | FIXNUM_FLAG)
VALUE rb_int2inum _((long)); VALUE rb_int2inum _((long));
#define INT2NUM(v) rb_int2inum(v) #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 FIX2LONG(x) RSHIFT((long)x,1)
#define FIX2ULONG(x) (((unsigned long)(x))>>1) #define FIX2ULONG(x) (((unsigned long)(x))>>1)
@ -271,14 +273,14 @@ struct RFile {
struct RData { struct RData {
struct RBasic basic; struct RBasic basic;
void (*dmark)(); void (*dmark) _((void*));
void (*dfree)(); void (*dfree) _((void*));
void *data; void *data;
}; };
#define DATA_PTR(dta) (RDATA(dta)->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) (\ #define Data_Make_Struct(klass,type,mark,free,sval) (\
sval = ALLOC(type),\ sval = ALLOC(type),\
memset(sval, 0, sizeof(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_virtual_variable _((const char*,VALUE(*)(),void(*)()));
void rb_define_hooked_variable _((const char*,VALUE*,VALUE(*)(),void(*)())); void rb_define_hooked_variable _((const char*,VALUE*,VALUE(*)(),void(*)()));
void rb_define_readonly_variable _((const char*,VALUE*)); void rb_define_readonly_variable _((const char*,VALUE*));
void rb_define_shared_variable _((VALUE,const char*,VALUE)); void rb_define_constants _((VALUE,const char*,VALUE));
void rb_define_global_shared_variable _((const char*,VALUE)); void rb_define_global_constants _((const char*,VALUE));
void rb_define_method _((VALUE,const char*,VALUE(*)(),int)); void rb_define_method _((VALUE,const char*,VALUE(*)(),int));
void rb_define_module_function _((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_eTypeError;
EXTERN VALUE rb_eZeroDivError; EXTERN VALUE rb_eZeroDivError;
EXTERN VALUE rb_eNotImpError; EXTERN VALUE rb_eNotImpError;
EXTERN VALUE rb_eNoMemError;
EXTERN VALUE rb_eFloatDomainError; EXTERN VALUE rb_eFloatDomainError;
#if defined(__GNUC__) && __GNUC__ >= 2 && !defined(RUBY_NO_INLINE) #if defined(__GNUC__) && __GNUC__ >= 2 && !defined(RUBY_NO_INLINE)

View file

@ -66,7 +66,7 @@ rb_tainted_str_new(ptr, len)
{ {
VALUE str = rb_str_new(ptr, len); VALUE str = rb_str_new(ptr, len);
FL_SET(str, FL_TAINT); OBJ_TAINT(str);
return str; return str;
} }
@ -76,7 +76,7 @@ rb_tainted_str_new2(ptr)
{ {
VALUE str = rb_str_new2(ptr); VALUE str = rb_str_new2(ptr);
FL_SET(str, FL_TAINT); OBJ_TAINT(str);
return str; return str;
} }
@ -112,8 +112,8 @@ rb_str_new4(orig)
str->ptr = RSTRING(orig)->ptr; str->ptr = RSTRING(orig)->ptr;
RSTRING(orig)->orig = (VALUE)str; RSTRING(orig)->orig = (VALUE)str;
str->orig = 0; str->orig = 0;
if (FL_TEST(orig, FL_TAINT)) { if (OBJ_TAINTED(orig)) {
FL_SET(str, FL_TAINT); OBJ_TAINT(str);
} }
FL_SET(str, STR_FREEZE); FL_SET(str, STR_FREEZE);
return (VALUE)str; return (VALUE)str;
@ -213,7 +213,7 @@ rb_str_s_new(klass, orig)
} }
if (rb_safe_level() >= 3) { if (rb_safe_level() >= 3) {
FL_SET(str, FL_TAINT); OBJ_TAINT(str);
} }
return (VALUE)str; return (VALUE)str;
@ -334,7 +334,7 @@ rb_str_modify(str)
if (FL_TEST(str, STR_FREEZE)) if (FL_TEST(str, STR_FREEZE))
rb_raise(rb_eTypeError, "can't modify frozen string"); 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"); rb_raise(rb_eSecurityError, "Insecure: can't modify string");
if (!RSTRING(str)->orig || FL_TEST(str, STR_NO_ORIG)) return; if (!RSTRING(str)->orig || FL_TEST(str, STR_NO_ORIG)) return;
ptr = RSTRING(str)->ptr; ptr = RSTRING(str)->ptr;
@ -350,6 +350,9 @@ VALUE
rb_str_freeze(str) rb_str_freeze(str)
VALUE 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); FL_SET(str, STR_FREEZE);
return str; return str;
} }
@ -585,6 +588,7 @@ rb_str_index_method(argc, argv, str)
switch (TYPE(sub)) { switch (TYPE(sub)) {
case T_REGEXP: case T_REGEXP:
pos = rb_reg_adjust_startpos(sub, str, pos, 0);
pos = rb_reg_search(sub, str, pos, 0); pos = rb_reg_search(sub, str, pos, 0);
break; break;
@ -635,6 +639,7 @@ rb_str_rindex(argc, argv, str)
switch (TYPE(sub)) { switch (TYPE(sub)) {
case T_REGEXP: case T_REGEXP:
if (RREGEXP(sub)->len) { if (RREGEXP(sub)->len) {
pos = rb_reg_adjust_startpos(sub, str, pos, 1);
pos = rb_reg_search(sub, str, pos, 1); pos = rb_reg_search(sub, str, pos, 1);
} }
if (pos >= 0) return INT2NUM(pos); if (pos >= 0) return INT2NUM(pos);

View file

@ -161,7 +161,7 @@ make_struct(name, member, klass)
else { else {
char *cname = STR2CSTR(name); char *cname = STR2CSTR(name);
id = rb_intern(cname); 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); rb_raise(rb_eNameError, "identifier %s needs to be constant", cname);
} }
nstr = rb_define_class_under(klass, cname, klass); nstr = rb_define_class_under(klass, cname, klass);
@ -207,7 +207,8 @@ rb_struct_define(name, va_alist)
VALUE nm, ary; VALUE nm, ary;
char *mem; char *mem;
nm = rb_str_new2(name); if (!name) nm = Qnil;
else nm = rb_str_new2(name);
ary = rb_ary_new(); ary = rb_ary_new();
va_init_list(ar, name); va_init_list(ar, name);
@ -224,16 +225,23 @@ static VALUE
rb_struct_s_def(argc, argv, klass) rb_struct_s_def(argc, argv, klass)
int argc; int argc;
VALUE *argv; VALUE *argv;
VALUE klass;
{ {
VALUE name, rest; VALUE name, rest;
long i; long i;
VALUE st; VALUE st;
ID id;
rb_scan_args(argc, argv, "1*", &name, &rest); rb_scan_args(argc, argv, "1*", &name, &rest);
for (i=0; i<RARRAY(rest)->len; i++) { for (i=0; i<RARRAY(rest)->len; i++) {
ID id = rb_to_id(RARRAY(rest)->ptr[i]); id = rb_to_id(RARRAY(rest)->ptr[i]);
RARRAY(rest)->ptr[i] = INT2FIX(id); 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); st = make_struct(name, rest, klass);
return st; return st;

View file

@ -44,7 +44,7 @@ fc_i(key, value, res)
VALUE path; VALUE path;
char *name; char *name;
if (!rb_is_shared_id(key)) return ST_CONTINUE; if (!rb_is_const_id(key)) return ST_CONTINUE;
name = rb_id2name(key); name = rb_id2name(key);
if (res->path) { if (res->path) {
@ -226,7 +226,7 @@ rb_autoload_id(id, filename)
ID id; ID id;
const char *filename; 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_raise(rb_eNameError, "autoload must be constant name",
rb_id2name(id)); rb_id2name(id));
} }
@ -858,7 +858,7 @@ rb_ivar_get(obj, id)
{ {
VALUE val; 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"); rb_raise(rb_eSecurityError, "Insecure: can't access instance variable");
switch (TYPE(obj)) { switch (TYPE(obj)) {
case T_OBJECT: case T_OBJECT:
@ -873,7 +873,7 @@ rb_ivar_get(obj, id)
break; break;
} }
if (ruby_verbose) { 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; return Qnil;
} }
@ -884,7 +884,7 @@ rb_ivar_set(obj, id, val)
ID id; ID id;
VALUE val; 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"); rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
switch (TYPE(obj)) { switch (TYPE(obj)) {
case T_OBJECT: case T_OBJECT:
@ -936,10 +936,11 @@ VALUE
rb_obj_instance_variables(obj) rb_obj_instance_variables(obj)
VALUE 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"); rb_raise(rb_eSecurityError, "Insecure: can't get metainfo");
ary = rb_ary_new();
switch (TYPE(obj)) { switch (TYPE(obj)) {
case T_OBJECT: case T_OBJECT:
case T_CLASS: case T_CLASS:
@ -969,7 +970,7 @@ rb_obj_remove_instance_variable(obj, name)
VALUE val = Qnil; VALUE val = Qnil;
ID id = rb_to_id(name); 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"); rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
if (!rb_is_instance_id(id)) { if (!rb_is_instance_id(id)) {
rb_raise(rb_eNameError, "`%s' is not an instance variable", rb_raise(rb_eNameError, "`%s' is not an instance variable",
@ -993,7 +994,7 @@ rb_obj_remove_instance_variable(obj, name)
} }
VALUE VALUE
rb_shvar_get_at(klass, id) rb_const_get_at(klass, id)
VALUE klass; VALUE klass;
ID id; ID id;
{ {
@ -1003,7 +1004,7 @@ rb_shvar_get_at(klass, id)
return value; return value;
} }
if (klass == rb_cObject) { if (klass == rb_cObject) {
return rb_shvar_get(klass, id); return rb_const_get(klass, id);
} }
rb_raise(rb_eNameError, "uninitialized constant %s::%s", rb_raise(rb_eNameError, "uninitialized constant %s::%s",
RSTRING(rb_class_path(klass))->ptr, RSTRING(rb_class_path(klass))->ptr,
@ -1012,16 +1013,21 @@ rb_shvar_get_at(klass, id)
} }
VALUE void
rb_const_get_at(klass, id) rb_autoload_load(id)
VALUE klass;
ID 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 VALUE
rb_shvar_get(klass, id) rb_const_get(klass, id)
VALUE klass; VALUE klass;
ID id; ID id;
{ {
@ -1036,7 +1042,7 @@ rb_shvar_get(klass, id)
tmp = RCLASS(tmp)->super; tmp = RCLASS(tmp)->super;
} }
if (BUILTIN_TYPE(klass) == T_MODULE) { if (BUILTIN_TYPE(klass) == T_MODULE) {
return rb_shvar_get(rb_cObject, id); return rb_const_get(rb_cObject, id);
} }
/* pre-defined class */ /* pre-defined class */
@ -1044,14 +1050,8 @@ rb_shvar_get(klass, id)
/* autoload */ /* autoload */
if (autoload_tbl && st_lookup(autoload_tbl, id, 0)) { if (autoload_tbl && st_lookup(autoload_tbl, id, 0)) {
char *modname; rb_autoload_load(id);
VALUE module; return rb_const_get(klass, id);
st_delete(autoload_tbl, &id, &modname);
module = rb_str_new2(modname);
free(modname);
rb_f_require(Qnil, module);
return rb_shvar_get(klass, id);
} }
/* Uninitialized constant */ /* Uninitialized constant */
@ -1065,21 +1065,13 @@ rb_shvar_get(klass, id)
return Qnil; /* not reached */ return Qnil; /* not reached */
} }
VALUE
rb_const_get(klass, id)
VALUE klass;
ID id;
{
return rb_shvar_get(klass, id);
}
static int static int
sv_i(key, value, ary) sv_i(key, value, ary)
ID key; ID key;
VALUE value; VALUE value;
VALUE ary; VALUE ary;
{ {
if (rb_is_shared_id(key)) { if (rb_is_const_id(key)) {
VALUE kval = rb_str_new2(rb_id2name(key)); VALUE kval = rb_str_new2(rb_id2name(key));
if (!rb_ary_includes(ary, kval)) { if (!rb_ary_includes(ary, kval)) {
rb_ary_push(ary, kval); rb_ary_push(ary, kval);
@ -1089,20 +1081,22 @@ sv_i(key, value, ary)
} }
VALUE VALUE
rb_mod_remove_shvar(mod, name) rb_mod_remove_const(mod, name)
VALUE mod, name; VALUE mod, name;
{ {
ID id = rb_to_id(name); ID id = rb_to_id(name);
VALUE val; VALUE val;
if (!rb_is_shared_id(id)) { if (!OBJ_TAINTED(mod) && rb_safe_level() >= 4)
rb_raise(rb_eNameError, "`%s' is not shared variable", rb_id2name(id)); 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)) { if (RCLASS(mod)->iv_tbl && st_delete(ROBJECT(mod)->iv_tbl, &id, &val)) {
return 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_raise(rb_eNameError, "cannot remove %s::%s",
rb_class2name(mod), rb_id2name(id)); rb_class2name(mod), rb_id2name(id));
} }
@ -1111,13 +1105,6 @@ rb_mod_remove_shvar(mod, name)
return Qnil; /* not reached */ return Qnil; /* not reached */
} }
VALUE
rb_mod_remove_const(mod, name)
VALUE mod, name;
{
return rb_mod_remove_shvar(mod, name);
}
static int static int
autoload_i(key, name, ary) autoload_i(key, name, ary)
ID key; ID key;
@ -1132,10 +1119,10 @@ autoload_i(key, name, ary)
} }
VALUE VALUE
rb_mod_shvar_at(mod, ary) rb_mod_const_at(mod, ary)
VALUE 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"); rb_raise(rb_eSecurityError, "Insecure: can't get metainfo");
if (RCLASS(mod)->iv_tbl) { if (RCLASS(mod)->iv_tbl) {
st_foreach(RCLASS(mod)->iv_tbl, sv_i, ary); st_foreach(RCLASS(mod)->iv_tbl, sv_i, ary);
@ -1149,61 +1136,25 @@ rb_mod_shvar_at(mod, ary)
return ary; return 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)
VALUE mod;
VALUE ary;
{
rb_mod_shvar_at(mod, ary);
for (;;) {
mod = RCLASS(mod)->super;
if (!mod) break;
rb_mod_shvar_at(mod, ary);
}
return ary;
}
VALUE VALUE
rb_mod_const_of(mod, ary) rb_mod_const_of(mod, ary)
VALUE mod; VALUE mod;
VALUE ary; VALUE ary;
{ {
return rb_mod_shvar_of(mod, ary); rb_mod_const_at(mod, ary);
for (;;) {
mod = RCLASS(mod)->super;
if (!mod) break;
rb_mod_const_at(mod, ary);
} }
return ary;
VALUE
rb_mod_shvars(mod)
VALUE mod;
{
return rb_mod_shvar_of(mod, rb_ary_new());
} }
VALUE VALUE
rb_mod_constants(mod) rb_mod_constants(mod)
VALUE mod; VALUE mod;
{ {
return rb_mod_shvars(mod); return rb_mod_const_of(mod, rb_ary_new());
}
int
rb_shvar_defined_at(klass, id)
VALUE klass;
ID id;
{
if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, 0)) {
return Qtrue;
}
if (klass == rb_cObject) {
return rb_shvar_defined(klass, id);
}
return Qfalse;
} }
int int
@ -1211,7 +1162,13 @@ rb_const_defined_at(klass, id)
VALUE klass; VALUE klass;
ID id; ID id;
{ {
return rb_shvar_defined_at(klass, id); if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, 0)) {
return Qtrue;
}
if (klass == rb_cObject) {
return rb_const_defined(klass, id);
}
return Qfalse;
} }
int int
@ -1224,7 +1181,7 @@ rb_autoload_defined(id)
} }
int int
rb_shvar_defined(klass, id) rb_const_defined(klass, id)
VALUE klass; VALUE klass;
ID id; ID id;
{ {
@ -1237,28 +1194,20 @@ rb_shvar_defined(klass, id)
tmp = RCLASS(tmp)->super; tmp = RCLASS(tmp)->super;
} }
if (BUILTIN_TYPE(klass) == T_MODULE) { 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)) if (st_lookup(rb_class_tbl, id, 0))
return Qtrue; return Qtrue;
return rb_autoload_defined(id); return rb_autoload_defined(id);
} }
int
rb_const_defined(klass, id)
VALUE klass;
ID id;
{
return rb_shvar_defined(klass, id);
}
void void
rb_shvar_set(klass, id, val) rb_const_set(klass, id, val)
VALUE klass; VALUE klass;
ID id; ID id;
VALUE val; 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"); rb_raise(rb_eSecurityError, "Insecure: can't set constant");
if (!RCLASS(klass)->iv_tbl) { if (!RCLASS(klass)->iv_tbl) {
RCLASS(klass)->iv_tbl = st_init_numtable(); RCLASS(klass)->iv_tbl = st_init_numtable();
@ -1268,16 +1217,7 @@ rb_shvar_set(klass, id, val)
} }
void void
rb_const_set(klass, id, val) rb_const_assign(klass, id, val)
VALUE klass;
ID id;
VALUE val;
{
rb_shvar_set(klass, id, val);
}
void
rb_shvar_assign(klass, id, val)
VALUE klass; VALUE klass;
ID id; ID id;
VALUE val; VALUE val;
@ -1329,19 +1269,10 @@ rb_define_const(klass, name, val)
if (klass == rb_cObject) { if (klass == rb_cObject) {
rb_secure(4); rb_secure(4);
} }
if (!rb_is_shared_id(id)) { if (!rb_is_const_id(id)) {
rb_raise(rb_eNameError, "wrong shared variable name %s", name); rb_raise(rb_eNameError, "wrong constant name %s", name);
} }
rb_shvar_set(klass, id, val); rb_const_set(klass, id, val);
}
void
rb_define_shvar(klass, name, val)
VALUE klass;
const char *name;
VALUE val;
{
rb_define_const(klass, name, val);
} }
void void
@ -1352,14 +1283,6 @@ rb_define_global_const(name, val)
rb_define_const(rb_cObject, 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 VALUE
rb_iv_get(obj, name) rb_iv_get(obj, name)
VALUE obj; VALUE obj;

View file

@ -1,4 +1,4 @@
#define RUBY_VERSION "1.5.0" #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_VERSION_CODE 150
#define RUBY_RELEASE_CODE 19991207 #define RUBY_RELEASE_CODE 19991214

View file

@ -35,7 +35,7 @@ s%@RANLIB@%rem%g
s%@AR@%lib -nologo%g s%@AR@%lib -nologo%g
s%@LN_S@%%g s%@LN_S@%%g
s%@SET_MAKE@%%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%@ALLOCA@%%g
s%@DEFAULT_KCODE@%%g s%@DEFAULT_KCODE@%%g
s%@EXEEXT@%.exe%g s%@EXEEXT@%.exe%g