summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog52
-rw-r--r--README2
-rw-r--r--README.jp2
-rw-r--r--array.c5
-rw-r--r--class.c27
-rw-r--r--configure4
-rw-r--r--configure.in4
-rw-r--r--dir.c4
-rw-r--r--error.c3
-rw-r--r--eval.c477
-rw-r--r--ext/dbm/dbm.c7
-rw-r--r--ext/gdbm/gdbm.c15
-rw-r--r--ext/socket/socket.c17
-rw-r--r--ext/tk/lib/tk.rb6
-rw-r--r--file.c21
-rw-r--r--gc.c30
-rw-r--r--hash.c5
-rw-r--r--intern.h23
-rw-r--r--io.c20
-rw-r--r--misc/ruby-mode.el7
-rw-r--r--object.c29
-rw-r--r--parse.y38
-rw-r--r--process.c7
-rw-r--r--range.c14
-rw-r--r--re.c26
-rw-r--r--re.h1
-rw-r--r--regex.c61
-rw-r--r--regex.h3
-rw-r--r--ruby.h15
-rw-r--r--string.c17
-rw-r--r--struct.c14
-rw-r--r--variable.c171
-rw-r--r--version.h4
-rw-r--r--win32/config.status2
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 <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>
* 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はテキスト処理関係の能力などに優れ,Perlと同じくらい強力
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 TkListbox<TkTextWin
def nearest(y)
tk_send('nearest', y).to_i
end
- def size(y)
+ def size
tk_send('size').to_i
end
def selection_anchor(index)
@@ -2159,8 +2159,8 @@ class TkListbox<TkTextWin
def selection_clear(first, last=None)
tk_send 'selection', 'clear', first, last
end
- def selection_includes
- bool(tk_send('selection', 'includes'))
+ def selection_includes(index)
+ bool(tk_send('selection', 'includes', index))
end
def selection_set(first, last=None)
tk_send 'selection', 'set', first, last
diff --git a/file.c b/file.c
index e34a6f3a50..deaa40d9b4 100644
--- a/file.c
+++ b/file.c
@@ -102,7 +102,7 @@ rb_file_path(obj)
OpenFile *fptr;
GetOpenFile(obj, fptr);
- if (fptr->path == 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;
@@ -4549,18 +4548,11 @@ rb_id2name(id)
}
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
@@ -508,6 +508,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;
int pos, reverse;
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 <limits.h>
@@ -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; 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);
}
+ 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,20 +1166,12 @@ 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