From: "H.Yamamoto" Date: 2006-02-02T19:45:51+09:00 Subject: Re: [ ruby-Bugs-3399 ] [PATCH] OS X core dumps when $0 is changed and then loads shared libraries Hello. >The problem is that Ruby is setting argv[1..argc-1] to 0 and OS X's dyld >expects those to not be 0 as it uses them. Postgres had the same problem >and describes why dyld uses argv: > >http://archives.postgresql.org/pgsql-hackers/2003-11/msg00449.php Interesting, but Starndard C gurantees argc and argv should be modifiable, so I think this is OSX's bug. >It's not clear to me why in one branch of the function at the end, >origargv[1..argc-1] are set to 0 and in the other they are not. Just out >of consistently, it seems better to have both treat origargv[1..argc-1] the >same and not set them to 0, which also prevents this core dump. > >Here's the patch: > >diff -ru ruby-1.8.4.orig/ruby.c ruby-1.8.4/ruby.c >--- ruby-1.8.4.orig/ruby.c 2005-12-11 16:36:52.000000000 -0800 >+++ ruby-1.8.4/ruby.c 2006-01-31 22:13:18.000000000 -0800 >@@ -1067,8 +1067,6 @@ > *s++ = '\0'; > while (++i < len) > *s++ = ' '; >- for (i = 1; i < origargc; i++) >- origargv[i] = 0; > } > rb_progname = rb_tainted_str_new2(origargv[0]); > #endif If this patch is applied, for example after set_arg0 origargv[i] (i >= 1) can point to the location which is filled with ' ', and can be unterminated with '\0' like this "fooboofoo\0 ?" ^ origargv[1] if '?' != '\0', strlen(origargv[i]) will access out of memory block How about this? This is shorter, probably safer. Index: ruby.c =================================================================== RCS file: /src/ruby/ruby.c,v retrieving revision 1.83.2.13 diff -u -w -b -p -r1.83.2.13 ruby.c --- ruby.c 1 Feb 2006 13:27:47 -0000 1.83.2.13 +++ ruby.c 2 Feb 2006 10:28:25 -0000 @@ -1065,18 +1065,9 @@ set_arg0(val, id) if (i >= len) { i = len; - memcpy(origargv[0], s, i); - origargv[0][i] = '\0'; } - else { memcpy(origargv[0], s, i); - s = origargv[0]+i; - *s++ = '\0'; - while (++i < len) - *s++ = ' '; - for (i = 1; i < origargc; i++) - origargv[i] = 0; - } + memset(origargv[0] + i, '\0', len - i + 1); rb_progname = rb_tainted_str_new2(origargv[0]); #endif }