summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog76
-rw-r--r--array.c22
-rw-r--r--enum.c7
-rw-r--r--eval.c61
-rw-r--r--ext/dbm/dbm.c1
-rw-r--r--ext/sdbm/init.c1
-rw-r--r--ext/socket/socket.c12
-rw-r--r--ext/zlib/zlib.c1
-rw-r--r--gc.c174
-rw-r--r--intern.h1
-rw-r--r--lib/delegate.rb14
-rw-r--r--string.c10
12 files changed, 271 insertions, 109 deletions
diff --git a/ChangeLog b/ChangeLog
index af92ac5..c33628e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+Wed Oct 20 19:45:13 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (str_gsub): reentrant check. [ruby-dev:24432]
+
+ * backport all SEGV bug fixes from CVS HEAD. [ruby-dev:24536]
+
+Wed Oct 20 04:17:55 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/dbm/dbm.c (fdbm_delete_if): should check if deleting element
+ is a string. [ruby-dev:24490]
+
+ * ext/sdbm/init.c (fsdbm_delete_if): ditto.
+
+Wed Oct 20 01:37:18 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_times): Array#* should return an instance of
+ the class of right operand. [ruby-dev:24526]
+
+ * ext/zlib/zlib.c (zstream_detach_buffer): should not expose
+ class-less object to Ruby world. [ruby-dev:24530]
+
+ * eval.c (proc_dup): provide Proc#dup as well. [ruby-talk:116915]
+
+ * eval.c (ruby_exec): stack marking position may be higher than
+ expected. thanks to Guy Decoux. [ruby-core:03527]
+
Tue Oct 19 22:43:12 2004 Dave Thomas <dave@pragprog.com>
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_attr): If
@@ -36,6 +62,8 @@ Tue Oct 19 08:46:57 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
* string.c (rb_str_upto): method result must be checked. [ruby-dev:24504]
+ * eval.c (error_print): ditto. [ruby-dev:24519]
+
Mon Oct 18 23:37:05 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
* marshal.c (r_object0): check inheritance by the internal function.
@@ -6025,6 +6053,11 @@ Mon Oct 20 09:45:12 2003 NAKAMURA Usaku <usa@ruby-lang.org>
* lib/debug.rb (debug_command): remove debug print.
+Wed Oct 20 00:25:41 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * eval.c (search_required): required name must not be changed before
+ loading. [ruby-dev:24492]
+
Sun Oct 19 13:12:30 2003 Tanaka Akira <akr@m17n.org>
* lib/pathname.rb (foreachline, dir_foreach): add obsolete warning.
@@ -7008,6 +7041,35 @@ Thu Oct 2 00:21:11 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
* test/soap/calc/*: give httpd config param "CGIInterpreter".
"/usr/bin/env ruby" thing does not work under non-Unix boxes.
+Sat Oct 2 00:42:20 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * marshal.c (r_byte): retrieve pointer from string value for each
+ time. [ruby-dev:24404]
+
+ * marshal.c (r_bytes0): ditto.
+
+ * enum.c (sort_by_i): re-entrance check added. [ruby-dev:24399]
+
+ * io.c (io_read): should freeze all reading buffer.
+ [ruby-dev:24400]
+
+ * string.c (rb_str_sum): should use bignums when bits is greater
+ than or equals to sizeof(long)*CHAR_BITS. [ruby-dev:24395]
+
+ * eval.c (specific_eval): defer pointer retrieval to prevent
+ unsafe sourcefile string modification. [ruby-dev:24382]
+
+ * string.c (rb_str_sum): wrong cast caused wrong result.
+ [ruby-dev:24385]
+
+ * enum.c (enum_sort_by): hide temporary array from
+ ObjectSpace.each_object. [ruby-dev:24386]
+
+ * string.c (rb_str_sum): check was done with false pointer.
+ [ruby-dev:24383]
+
+ * string.c (rb_str_sum): string may be altered. [ruby-dev:24381]
+
Thu Oct 2 00:25:21 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
* signal.c (ruby_signal_name): adjust to the prototype.
@@ -7171,6 +7233,20 @@ Sat Sep 27 09:44:18 2003 Minero Aoki <aamine@loveruby.net>
* test/fileutils/test_nowrite.rb: ditto.
+Mon Sep 27 09:14:03 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_delete): comparison may change the capacity.
+ [ruby-dev:24348]
+
+ * array.c (rb_ary_fill): fill should honor length argument.
+ [ruby-dev:24346]
+
+ * array.c (rb_ary_replace): should not use ptr from shared array.
+ [ruby-dev:24345]
+
+ * ext/socket/socket.c (s_accept): don't retry for EWOULDBLOCK.
+ [ruby-talk:113807]
+
Sat Sep 27 04:57:07 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
* test/ruby/test_file.rb: new file. only asserts unlink-before-close
diff --git a/array.c b/array.c
index 3fe872b..26f56be 100644
--- a/array.c
+++ b/array.c
@@ -1855,8 +1855,7 @@ rb_ary_delete(ary, item)
if (rb_equal(e, item)) continue;
if (i1 != i2) {
- if (RARRAY(ary)->len < i2) break;
- RARRAY(ary)->ptr[i2] = e;
+ rb_ary_store(ary, i2, e);
}
i2++;
}
@@ -1867,12 +1866,13 @@ rb_ary_delete(ary, item)
return Qnil;
}
- if (RARRAY(ary)->len > i2)
+ if (RARRAY(ary)->len > i2) {
RARRAY(ary)->len = i2;
- if (i2 * 2 < RARRAY(ary)->aux.capa &&
+ if (i2 * 2 < RARRAY(ary)->aux.capa &&
RARRAY(ary)->aux.capa > ARY_DEFAULT_SIZE) {
- REALLOC_N(RARRAY(ary)->ptr, VALUE, i2 * 2);
- RARRAY(ary)->aux.capa = i2 * 2;
+ REALLOC_N(RARRAY(ary)->ptr, VALUE, i2 * 2);
+ RARRAY(ary)->aux.capa = i2 * 2;
+ }
}
return item;
@@ -2170,8 +2170,8 @@ rb_ary_replace(copy, orig)
shared = ary_make_shared(orig);
if (RARRAY(copy)->ptr && !FL_TEST(copy, ELTS_SHARED))
free(RARRAY(copy)->ptr);
- RARRAY(copy)->ptr = RARRAY(shared)->ptr;
- RARRAY(copy)->len = RARRAY(shared)->len;
+ RARRAY(copy)->ptr = RARRAY(orig)->ptr;
+ RARRAY(copy)->len = RARRAY(orig)->len;
RARRAY(copy)->aux.shared = shared;
FL_SET(copy, ELTS_SHARED);
@@ -2280,7 +2280,7 @@ rb_ary_fill(argc, argv, ary)
VALUE v;
long i;
- for (i=beg; i<RARRAY(ary)->len; i++) {
+ for (i=beg; i<end; i++) {
v = rb_yield(LONG2NUM(i));
if (i>=RARRAY(ary)->len) break;
RARRAY(ary)->ptr[i] = v;
@@ -2372,7 +2372,7 @@ rb_ary_times(ary, times)
}
len = NUM2LONG(times);
- if (len == 0) return rb_ary_new2(0);
+ if (len == 0) return ary_new(rb_obj_class(ary), 0);
if (len < 0) {
rb_raise(rb_eArgError, "negative argument");
}
@@ -2890,7 +2890,7 @@ flatten(ary, idx, ary2, memo)
while (i < lim) {
VALUE tmp;
- tmp = rb_check_array_type(RARRAY(ary)->ptr[i]);
+ tmp = rb_check_array_type(rb_ary_elt(ary, i));
if (!NIL_P(tmp)) {
n = flatten(ary, i, tmp, memo);
i += n; lim += n;
diff --git a/enum.c b/enum.c
index 9bf68f7..2f931c7 100644
--- a/enum.c
+++ b/enum.c
@@ -389,6 +389,9 @@ sort_by_i(i, ary)
NODE *memo;
v = rb_yield(i);
+ if (RBASIC(ary)->klass) {
+ rb_raise(rb_eRuntimeError, "sort_by reentered");
+ }
memo = rb_node_newnode(NODE_MEMO, v, i, 0);
rb_ary_push(ary, (VALUE)memo);
return Qnil;
@@ -486,6 +489,7 @@ enum_sort_by(obj)
else {
ary = rb_ary_new();
}
+ RBASIC(ary)->klass = 0;
rb_iterate(rb_each, obj, sort_by_i, ary);
if (RARRAY(ary)->len > 1) {
qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE), sort_by_cmp, 0);
@@ -493,6 +497,7 @@ enum_sort_by(obj)
for (i=0; i<RARRAY(ary)->len; i++) {
RARRAY(ary)->ptr[i] = RNODE(RARRAY(ary)->ptr[i])->u2.value;
}
+ RBASIC(ary)->klass = rb_cArray;
return ary;
}
@@ -879,7 +884,7 @@ enum_zip(argc, argv, obj)
NODE *memo;
for (i=0; i<argc; i++) {
- argv[i] = rb_convert_type(argv[i], T_ARRAY, "Array", "to_ary");
+ argv[i] = rb_convert_type(argv[i], T_ARRAY, "Array", "to_a");
}
result = rb_block_given_p() ? Qnil : rb_ary_new();
memo = rb_node_newnode(NODE_MEMO, result, rb_ary_new4(argc, argv), 0);
diff --git a/eval.c b/eval.c
index 9236df7..84ffab3 100644
--- a/eval.c
+++ b/eval.c
@@ -1127,7 +1127,8 @@ error_print()
eclass = CLASS_OF(ruby_errinfo);
if (EXEC_TAG() == 0) {
- e = rb_obj_as_string(ruby_errinfo);
+ e = rb_funcall(ruby_errinfo, rb_intern("message"), 0, 0);
+ StringValue(e);
einfo = RSTRING(e)->ptr;
elen = RSTRING(e)->len;
}
@@ -1441,13 +1442,11 @@ ruby_cleanup(ex)
return ex;
}
-int
-ruby_exec()
+static int
+ruby_exec_internal()
{
int state;
- volatile NODE *tmp;
- Init_stack((void*)&tmp);
PUSH_TAG(PROT_NONE);
PUSH_ITER(ITER_NOT);
/* default visibility is private at toplevel */
@@ -1467,6 +1466,15 @@ ruby_stop(ex)
exit(ruby_cleanup(ex));
}
+int
+ruby_exec()
+{
+ volatile NODE *tmp;
+
+ Init_stack((void*)&tmp);
+ return ruby_exec_internal();
+}
+
void
ruby_run()
{
@@ -5472,6 +5480,7 @@ rb_call0(klass, recv, id, oid, argc, argv, body, nosuper)
if ((++tick & 0xff) == 0) {
CHECK_INTS; /* better than nothing */
stack_check();
+ rb_gc_finalize_deferred();
}
PUSH_ITER(itr);
PUSH_FRAME();
@@ -7800,6 +7809,21 @@ blk_copy_prev(block)
}
+static void
+blk_dup(dup, orig)
+ struct BLOCK *dup, *orig;
+{
+ MEMCPY(dup, orig, struct BLOCK, 1);
+ frame_dup(&dup->frame);
+
+ if (dup->iter) {
+ blk_copy_prev(dup);
+ }
+ else {
+ dup->prev = 0;
+ }
+}
+
/*
* MISSING: documentation
*/
@@ -7814,15 +7838,25 @@ proc_clone(self)
Data_Get_Struct(self, struct BLOCK, orig);
bind = Data_Make_Struct(rb_obj_class(self),struct BLOCK,blk_mark,blk_free,data);
CLONESETUP(bind, self);
- MEMCPY(data, orig, struct BLOCK, 1);
- frame_dup(&data->frame);
+ blk_dup(data, orig);
- if (data->iter) {
- blk_copy_prev(data);
- }
- else {
- data->prev = 0;
- }
+ return bind;
+}
+
+/*
+ * MISSING: documentation
+ */
+
+static VALUE
+proc_dup(self)
+ VALUE self;
+{
+ struct BLOCK *orig, *data;
+ VALUE bind;
+
+ Data_Get_Struct(self, struct BLOCK, orig);
+ bind = Data_Make_Struct(rb_obj_class(self),struct BLOCK,blk_mark,blk_free,data);
+ blk_dup(data, orig);
return bind;
}
@@ -9159,6 +9193,7 @@ Init_Proc()
rb_define_singleton_method(rb_cProc, "new", proc_s_new, -1);
rb_define_method(rb_cProc, "clone", proc_clone, 0);
+ rb_define_method(rb_cProc, "dup", proc_dup, 0);
rb_define_method(rb_cProc, "call", proc_call, -2);
rb_define_method(rb_cProc, "arity", proc_arity, 0);
rb_define_method(rb_cProc, "[]", proc_call, -2);
diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c
index 143b0a9..e609327 100644
--- a/ext/dbm/dbm.c
+++ b/ext/dbm/dbm.c
@@ -388,6 +388,7 @@ fdbm_delete_if(obj)
for (i = 0; i < RARRAY(ary)->len; i++) {
keystr = RARRAY(ary)->ptr[i];
+ StringValue(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
if (dbm_delete(dbm, key)) {
diff --git a/ext/sdbm/init.c b/ext/sdbm/init.c
index 0f9ae1d..ed39769 100644
--- a/ext/sdbm/init.c
+++ b/ext/sdbm/init.c
@@ -366,6 +366,7 @@ fsdbm_delete_if(obj)
for (i = 0; i < RARRAY(ary)->len; i++) {
keystr = RARRAY(ary)->ptr[i];
+ StringValue(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
if (sdbm_delete(dbm, key)) {
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index f9a821b..624ea9f 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -275,6 +275,8 @@ bsock_setsockopt(sock, lev, optname, val)
rb_secure(2);
level = NUM2INT(lev);
option = NUM2INT(optname);
+ GetOpenFile(sock, fptr);
+
switch (TYPE(val)) {
case T_FIXNUM:
i = FIX2INT(val);
@@ -294,7 +296,6 @@ bsock_setsockopt(sock, lev, optname, val)
break;
}
- GetOpenFile(sock, fptr);
if (setsockopt(fileno(fptr->f), level, option, v, vlen) < 0)
rb_sys_fail(fptr->path);
@@ -2095,7 +2096,7 @@ sock_s_gethostbyaddr(argc, argv)
t = AF_INET6;
}
#endif
- h = gethostbyaddr((char*)RSTRING(addr)->ptr, RSTRING(addr)->len, t);
+ h = gethostbyaddr(RSTRING(addr)->ptr, RSTRING(addr)->len, t);
if (h == NULL) {
#ifdef HAVE_HSTRERROR
extern int h_errno;
@@ -2136,14 +2137,15 @@ sock_s_getservbyaname(argc, argv)
rb_scan_args(argc, argv, "11", &service, &proto);
if (NIL_P(proto)) proto = rb_str_new2("tcp");
- else StringValue(proto);
+ StringValue(service);
+ StringValue(proto);
- sp = getservbyname((char*)RSTRING(service)->ptr, RSTRING(proto)->ptr);
+ sp = getservbyname(StringValueCStr(service), StringValueCStr(proto));
if (sp) {
port = ntohs(sp->s_port);
}
else {
- char *s = StringValuePtr(service);
+ char *s = RSTRING(service)->ptr;
char *end;
port = strtoul(s, &end, 0);
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index 412c982..0afd7e0 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -530,6 +530,7 @@ zstream_detach_buffer(z)
z->buf_filled = 0;
z->stream.next_out = 0;
z->stream.avail_out = 0;
+ RBASIC(dst)->klass = rb_cString;
return dst;
}
diff --git a/gc.c b/gc.c
index a32de71..3d901be 100644
--- a/gc.c
+++ b/gc.c
@@ -39,13 +39,21 @@
*/
#define __libc_ia64_register_backing_store_base (4ULL<<61)
#else
+#ifdef HAVE_UNWIND_H
+#include <unwind.h>
+#else
#pragma weak __libc_ia64_register_backing_store_base
extern unsigned long __libc_ia64_register_backing_store_base;
#endif
#endif
+#endif
+
+#if defined _WIN32 || defined __CYGWIN__
+#include <windows.h>
+#endif
void re_free_registers _((struct re_registers*));
-void rb_io_fptr_finalize _((struct OpenFile*));
+int rb_io_fptr_finalize _((struct OpenFile*));
#if !defined(setjmp) && defined(HAVE__SETJMP)
#define setjmp(env) _setjmp(env)
@@ -84,6 +92,7 @@ static unsigned long malloc_increase = 0;
static unsigned long malloc_limit = GC_MALLOC_LIMIT;
static void run_final();
static VALUE nomem_error;
+static void garbage_collect();
void
rb_memerror()
@@ -111,11 +120,11 @@ ruby_xmalloc(size)
malloc_increase += size;
if (malloc_increase > malloc_limit) {
- rb_gc();
+ garbage_collect();
}
RUBY_CRITICAL(mem = malloc(size));
if (!mem) {
- rb_gc();
+ garbage_collect();
RUBY_CRITICAL(mem = malloc(size));
if (!mem) {
rb_memerror();
@@ -152,7 +161,7 @@ ruby_xrealloc(ptr, size)
malloc_increase += size;
RUBY_CRITICAL(mem = realloc(ptr, size));
if (!mem) {
- rb_gc();
+ garbage_collect();
RUBY_CRITICAL(mem = realloc(ptr, size));
if (!mem) {
rb_memerror();
@@ -170,7 +179,6 @@ ruby_xfree(x)
RUBY_CRITICAL(free(x));
}
-extern int ruby_in_compile;
static int dont_gc;
static int during_gc;
static int need_call_final = 0;
@@ -373,7 +381,7 @@ rb_newobj()
{
VALUE obj;
- if (!freelist) rb_gc();
+ if (!freelist) garbage_collect();
obj = (VALUE)freelist;
freelist = freelist->as.free.next;
@@ -405,21 +413,22 @@ rb_data_object_alloc(klass, datap, dmark, dfree)
extern st_table *rb_class_tbl;
VALUE *rb_gc_stack_start = 0;
+#ifdef DJGPP
+/* set stack size (http://www.delorie.com/djgpp/v2faq/faq15_9.html) */
+unsigned int _stklen = 0x180000; /* 1.5 kB */
+#endif
+
#if defined(DJGPP) || defined(_WIN32_WCE)
static unsigned int STACK_LEVEL_MAX = 65535;
-#else
-#ifdef __human68k__
-extern unsigned int _stacksize;
+#elif defined(__human68k__)
+unsigned int _stacksize = 262144;
# define STACK_LEVEL_MAX (_stacksize - 4096)
# undef HAVE_GETRLIMIT
-#else
-#ifdef HAVE_GETRLIMIT
+#elif defined(HAVE_GETRLIMIT)
static unsigned int STACK_LEVEL_MAX = 655300;
#else
# define STACK_LEVEL_MAX 655300
#endif
-#endif
-#endif
#ifdef C_ALLOCA
# define SET_STACK_END VALUE stack_end; alloca(0);
@@ -983,25 +992,47 @@ gc_mark_children(ptr, lev)
static void obj_free _((VALUE));
static void
-gc_sweep()
+finalize_list(p)
+ RVALUE *p;
+{
+ while (p) {
+ RVALUE *tmp = p->as.free.next;
+ run_final((VALUE)p);
+ if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */
+ p->as.free.flags = 0;
+ p->as.free.next = freelist;
+ freelist = p;
+ }
+ p = tmp;
+ }
+}
+
+static void
+free_unused_heaps()
{
- RVALUE *p, *pend, *final_list;
- int freed = 0;
int i, j;
- unsigned long live = 0;
- if (ruby_in_compile && ruby_parser_stack_on_heap()) {
- /* should not reclaim nodes during compilation
- if yacc's semantic stack is not allocated on machine stack */
- for (i = 0; i < heaps_used; i++) {
- p = heaps[i].slot; pend = p + heaps[i].limit;
- while (p < pend) {
- if (!(p->as.basic.flags&FL_MARK) && BUILTIN_TYPE(p) == T_NODE)
- gc_mark((VALUE)p, 0);
- p++;
+ for (i = j = 1; j < heaps_used; i++) {
+ if (heaps[i].limit == 0) {
+ free(heaps[i].slot);
+ heaps_used--;
+ }
+ else {
+ if (i != j) {
+ heaps[j] = heaps[i];
}
+ j++;
}
}
+}
+
+static void
+gc_sweep()
+{
+ RVALUE *p, *pend, *final_list;
+ int freed = 0;
+ int i;
+ unsigned long live = 0;
mark_source_filename(ruby_sourcefile);
st_foreach(source_filenames, sweep_source_filename, 0);
@@ -1067,35 +1098,10 @@ gc_sweep()
/* clear finalization list */
if (final_list) {
- RVALUE *tmp;
-
- if (rb_prohibit_interrupt || ruby_in_compile) {
- deferred_final_list = final_list;
- return;
- }
-
- for (p = final_list; p; p = tmp) {
- tmp = p->as.free.next;
- run_final((VALUE)p);
- if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */
- p->as.free.flags = 0;
- p->as.free.next = freelist;
- freelist = p;
- }
- }
- }
- for (i = j = 1; j < heaps_used; i++) {
- if (heaps[i].limit == 0) {
- free(heaps[i].slot);
- heaps_used--;
- }
- else {
- if (i != j) {
- heaps[j] = heaps[i];
- }
- j++;
- }
+ deferred_final_list = final_list;
+ return;
}
+ free_unused_heaps();
}
void
@@ -1281,8 +1287,8 @@ int rb_setjmp (rb_jmp_buf);
#endif /* __human68k__ or DJGPP */
#endif /* __GNUC__ */
-void
-rb_gc()
+static void
+garbage_collect()
{
struct gc_list *list;
struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug?? */
@@ -1342,14 +1348,21 @@ rb_gc()
{
ucontext_t ctx;
VALUE *top, *bot;
+#ifdef HAVE_UNWIND_H
+ _Unwind_Context *unwctx = _UNW_createContextForSelf();
+#endif
+
getcontext(&ctx);
mark_locations_array((VALUE*)&ctx.uc_mcontext,
((size_t)(sizeof(VALUE)-1 + sizeof ctx.uc_mcontext)/sizeof(VALUE)));
- bot = (VALUE*)__libc_ia64_register_backing_store_base;
-#if defined(__FreeBSD__)
- top = (VALUE*)ctx.uc_mcontext.mc_special.bspstore;
+#ifdef HAVE_UNWIND_H
+ _UNW_currentContext(unwctx);
+ bot = (VALUE*)(long)_UNW_getAR(unwctx, _UNW_AR_BSP);
+ top = (VALUE*)(long)_UNW_getAR(unwctx, _UNW_AR_BSPSTORE);
+ _UNW_destroyContext(unwctx);
#else
- top = (VALUE*)ctx.uc_mcontext.sc_ar_bsp;
+ bot = (VALUE*)__libc_ia64_register_backing_store_base;
+ top = (VALUE*)ctx.uc_mcontext.IA64_BSPSTORE;
#endif
rb_gc_mark_locations(bot, top);
}
@@ -1387,6 +1400,13 @@ rb_gc()
gc_sweep();
}
+void
+rb_gc()
+{
+ garbage_collect();
+ rb_gc_finalize_deferred();
+}
+
/*
* call-seq:
* GC.start => nil
@@ -1408,9 +1428,16 @@ void
Init_stack(addr)
VALUE *addr;
{
-#if defined(__human68k__)
- extern void *_SEND;
- rb_gc_stack_start = _SEND;
+#if defined(_WIN32) || defined(__CYGWIN__)
+ MEMORY_BASIC_INFORMATION m;
+ memset(&m, 0, sizeof(m));
+ VirtualQuery(&m, &m, sizeof(m));
+ rb_gc_stack_start =
+ STACK_UPPER((VALUE *)&m, (VALUE *)m.BaseAddress,
+ (VALUE *)((char *)m.BaseAddress + m.RegionSize) - 1);
+#elif defined(STACK_END_ADDRESS)
+ extern void *STACK_END_ADDRESS;
+ rb_gc_stack_start = STACK_END_ADDRESS;
#else
if (!addr) addr = (VALUE *)&addr;
STACK_UPPER(&addr, addr, ++addr);
@@ -1765,6 +1792,18 @@ run_final(obj)
}
void
+rb_gc_finalize_deferred()
+{
+ RVALUE *p = deferred_final_list;
+
+ deferred_final_list = 0;
+ if (p) {
+ finalize_list(p);
+ free_unused_heaps();
+ }
+}
+
+void
rb_gc_call_finalizer_at_exit()
{
RVALUE *p, *pend;
@@ -1772,14 +1811,7 @@ rb_gc_call_finalizer_at_exit()
/* run finalizers */
if (need_call_final) {
- if (deferred_final_list) {
- p = deferred_final_list;
- while (p) {
- RVALUE *tmp = p;
- p = p->as.free.next;
- run_final((VALUE)tmp);
- }
- }
+ finalize_list(deferred_final_list);
for (i = 0; i < heaps_used; i++) {
p = heaps[i].slot; pend = p + heaps[i].limit;
while (p < pend) {
diff --git a/intern.h b/intern.h
index ece4990..61fb5b5 100644
--- a/intern.h
+++ b/intern.h
@@ -240,6 +240,7 @@ void rb_gc_mark _((VALUE));
void rb_gc_force_recycle _((VALUE));
void rb_gc _((void));
void rb_gc_copy_finalizer _((VALUE,VALUE));
+void rb_gc_finalize_deferred _((void));
void rb_gc_call_finalizer_at_exit _((void));
VALUE rb_gc_enable _((void));
VALUE rb_gc_disable _((void));
diff --git a/lib/delegate.rb b/lib/delegate.rb
index ee574cb..20e6b53 100644
--- a/lib/delegate.rb
+++ b/lib/delegate.rb
@@ -76,10 +76,14 @@ class SimpleDelegator<Delegator
@_sd_obj = obj
end
- def initialize_copy(obj)
+ def clone(obj)
super
__setobj__(obj.__getobj__.clone)
end
+ def dup(obj)
+ super
+ __setobj__(obj.__getobj__.dup)
+ end
end
# backward compatibility ^_^;;;
@@ -108,9 +112,13 @@ def DelegateClass(superclass)
def __setobj__(obj)
@_dc_obj = obj
end
- def initialize_copy(obj)
+ def clone(obj)
super
- __setobj__(obj.__getobj__.clone)
+ __setobj__(obj.__getobj__.clone)
+ end
+ def dup(obj)
+ super
+ __setobj__(obj.__getobj__.dup)
end
}
for method in methods
diff --git a/string.c b/string.c
index 675af12..9f00917 100644
--- a/string.c
+++ b/string.c
@@ -2037,6 +2037,9 @@ str_gsub(argc, argv, str, bang)
if (iter) {
rb_match_busy(match);
val = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match)));
+ if (RSTRING(str)->ptr == buf) {
+ rb_raise(rb_eRuntimeError, "gsub reentered");
+ }
rb_backref_set(match);
}
else {
@@ -4297,7 +4300,7 @@ rb_str_crypt(str, salt)
{
extern char *crypt();
VALUE result;
- char *s, *cr;
+ char *s;
StringValue(salt);
if (RSTRING(salt)->len < 2)
@@ -4305,10 +4308,7 @@ rb_str_crypt(str, salt)
if (RSTRING(str)->ptr) s = RSTRING(str)->ptr;
else s = "";
- cr = crypt(s, RSTRING(salt)->ptr);
- s = ALLOCA_N(char, strlen(cr));
- strcpy(s, cr);
- result = rb_str_new2(s);
+ result = rb_str_new2(crypt(s, RSTRING(salt)->ptr));
OBJ_INFECT(result, str);
OBJ_INFECT(result, salt);
return result;