diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-10-20 12:47:20 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-10-20 12:47:20 +0000 |
commit | 2ec51ee0d506c90f3afba694e6c502ef3d52e4f8 (patch) | |
tree | db3928abc44090d749b6609bfb7ef49f2631a5c9 | |
parent | 959077c8e0ec27dfa72025a85c99a4acc26f6491 (diff) | |
download | ruby-2ec51ee0d506c90f3afba694e6c502ef3d52e4f8.tar.gz |
* string.c (str_gsub): reentrant check. [ruby-dev:24432]
* backport all SEGV bug fixes from CVS HEAD. [ruby-dev:24536]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@7090 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 76 | ||||
-rw-r--r-- | array.c | 22 | ||||
-rw-r--r-- | enum.c | 7 | ||||
-rw-r--r-- | eval.c | 61 | ||||
-rw-r--r-- | ext/dbm/dbm.c | 1 | ||||
-rw-r--r-- | ext/sdbm/init.c | 1 | ||||
-rw-r--r-- | ext/socket/socket.c | 12 | ||||
-rw-r--r-- | ext/zlib/zlib.c | 1 | ||||
-rw-r--r-- | gc.c | 174 | ||||
-rw-r--r-- | intern.h | 1 | ||||
-rw-r--r-- | lib/delegate.rb | 14 | ||||
-rw-r--r-- | string.c | 10 |
12 files changed, 271 insertions, 109 deletions
@@ -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 @@ -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; @@ -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); @@ -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 143b0a9143..e609327c46 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 0f9ae1dbff..ed39769e7a 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 f9a821b55d..624ea9f2a6 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 412c98244a..0afd7e0152 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; } @@ -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) { @@ -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 ee574cb02b..20e6b53c2e 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 @@ -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; |