金井です。

2009年9月29日10:08 Yukihiro Matsumoto <matz / ruby-lang.org>:
> まつもと ゆきひろです
>
> In message "Re: [ruby-dev:39392] Re: Removing constant-able macros inside 
> of the loop."
>    on Mon, 28 Sep 2009 23:31:45 +0900, "Masahiro Kanai (CanI)" 
> <cani.m.61st / gmail.com> writes:
>
> |再チェックした結果、rb_str_{start, end}_with, rb_ary_timesが
> |rb_check_string_typeを実行する可能性がありましたが、
> |rb_ary_timesにおいては、RSTRING_PTR()の位置を工夫することで
> |対応が可能でした。(既に対応されてました。)
> |
> |
> |修正後のパッチは、以下の通りです。
>
> 試してみようと思いますが、残念ながらfoldされていてパッチが壊
> れてます。私が手で修正することはもちろん可能ですが、今後のた
> めにも、ぜひfoldしないようにして再投稿していただけるとありが
> たいです。

申し訳ありませんでした。
設定を確認して、再添付しました。

> あと、ChangeLogエントリもいただけるとすごくよいですが、こち
> らは必須ではありません。

過去のChangeLogや、以下のページのChangeLogの項目を参考にしながら書いてみました。 

<http://pub.cozmixng.org/~the-rwiki/rw-cgi.rb?cmd=view;name=CommitterHowto>
拙い文章ですが・・・

 * array.c (rb_ary_{times, shuffle_bang, sample}):
   removing constant-able macros inside of the loop. a patch from
   Masahiro Kanai (CanI) at [ruby-dev:number]. It was found out
   and fixed at Security and Programming camp 2009.

 * string.c (rb_str_{times, split_m}): ditto.

 * struct.c (rb_struct_{getmember, set, aref_id, aset_id},
   {make, inspect}_struct, recursive_{equal, hash, eql}): ditto.

パッチは、以下です。

--- array.c (revision 25052)
+++ array.c (working copy)
@@ -2708,8 +2708,8 @@
 static VALUE
 rb_ary_times(VALUE ary, VALUE times)
 {
-    VALUE ary2, tmp;
-    long i, len;
+    VALUE ary2, tmp, *ptr, *ptr2;
+    long i, t, len;

     tmp = rb_check_string_type(times);
     if (!NIL_P(tmp)) {
@@ -2732,8 +2732,11 @@
     ary2 = ary_new(rb_obj_class(ary), len);
     ARY_SET_LEN(ary2, len);

-    for (i=0; i<len; i+=RARRAY_LEN(ary)) {
- MEMCPY(RARRAY_PTR(ary2)+i, RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
+    ptr = RARRAY_PTR(ary);
+    ptr2 = RARRAY_PTR(ary2);
+    t = RARRAY_LEN(ary);
+    for (i=0; i<len; i+=t) {
+ MEMCPY(ptr2+i, ptr, VALUE, t);
     }
   out:
     OBJ_INFECT(ary2, ary);
@@ -3491,14 +3494,16 @@
 static VALUE
 rb_ary_shuffle_bang(VALUE ary)
 {
+    VALUE *ptr;
     long i = RARRAY_LEN(ary);

     rb_ary_modify(ary);
+    ptr = RARRAY_PTR(ary);
     while (i) {
  long j = (long)(rb_genrand_real()*i);
- VALUE tmp = RARRAY_PTR(ary)[--i];
- RARRAY_PTR(ary)[i] = RARRAY_PTR(ary)[j];
- RARRAY_PTR(ary)[j] = tmp;
+ VALUE tmp = ptr[--i];
+ ptr[i] = ptr[j];
+ ptr[j] = tmp;
     }
     return ary;
 }
@@ -3576,6 +3581,7 @@
  return rb_ary_new3(3, ptr[i], ptr[j], ptr[k]);
     }
     if ((size_t)n < sizeof(idx)/sizeof(idx[0])) {
+ VALUE *ptr_result;
  long sorted[sizeof(idx)/sizeof(idx[0])];
  sorted[0] = idx[0] = (long)(rb_genrand_real()*len);
  for (i=1; i<n; i++) {
@@ -3588,18 +3594,21 @@
      sorted[j] = idx[i] = k;
  }
  result = rb_ary_new2(n);
+ ptr_result = RARRAY_PTR(result);
  for (i=0; i<n; i++) {
-     RARRAY_PTR(result)[i] = RARRAY_PTR(ary)[idx[i]];
+     ptr_result[i] = ptr[idx[i]];
  }
     }
     else {
+ VALUE *ptr_result;
  result = rb_ary_new4(len, ptr);
+ ptr_result = RARRAY_PTR(result);
  RB_GC_GUARD(ary);
  for (i=0; i<n; i++) {
      j = (long)(rb_genrand_real()*(len-i)) + i;
-     nv = RARRAY_PTR(result)[j];
-     RARRAY_PTR(result)[j] = RARRAY_PTR(result)[i];
-     RARRAY_PTR(result)[i] = nv;
+     nv = ptr_result[j];
+     ptr_result[j] = ptr_result[i];
+     ptr_result[i] = nv;
  }
     }
     ARY_SET_LEN(result, n);
--- string.c (revision 25052)
+++ string.c (working copy)
@@ -1159,6 +1159,7 @@
 {
     VALUE str2;
     long n, len;
+    char *ptr2;

     len = NUM2LONG(times);
     if (len < 0) {
@@ -1169,16 +1170,17 @@
     }

     str2 = rb_str_new5(str, 0, len *= RSTRING_LEN(str));
+    ptr2 = RSTRING_PTR(str2);
     if (len) {
         n = RSTRING_LEN(str);
-        memcpy(RSTRING_PTR(str2), RSTRING_PTR(str), n);
+        memcpy(ptr2, RSTRING_PTR(str), n);
         while (n <= len/2) {
-            memcpy(RSTRING_PTR(str2) + n, RSTRING_PTR(str2), n);
+            memcpy(ptr2 + n, ptr2, n);
             n *= 2;
         }
-        memcpy(RSTRING_PTR(str2) + n, RSTRING_PTR(str2), len-n);
+        memcpy(ptr2 + n, ptr2, len-n);
     }
-    RSTRING_PTR(str2)[RSTRING_LEN(str2)] = '\0';
+    ptr2[RSTRING_LEN(str2)] = '\0';
     OBJ_INFECT(str2, str);
     rb_enc_cr_str_copy_for_substr(str2, str);

@@ -5701,6 +5703,7 @@
     }
     else if (split_type == string) {
  char *ptr = RSTRING_PTR(str);
+ char *temp = ptr;
  char *eptr = RSTRING_END(str);
  char *sptr = RSTRING_PTR(spat);
  long slen = RSTRING_LEN(spat);
@@ -5720,13 +5723,15 @@
   ptr = t;
   continue;
      }
-     rb_ary_push(result, rb_str_subseq(str, ptr - RSTRING_PTR(str), end));
+     rb_ary_push(result, rb_str_subseq(str, ptr - temp, end));
      ptr += end + slen;
      if (!NIL_P(limit) && lim <= ++i) break;
  }
- beg = ptr - RSTRING_PTR(str);
+ beg = ptr - temp;
     }
     else {
+ char *ptr = RSTRING_PTR(str);
+ long len = RSTRING_LEN(str);
  long start = beg;
  long idx;
  int last_null = 0;
@@ -5735,22 +5740,22 @@
  while ((end = rb_reg_search(spat, str, start, 0)) >= 0) {
      regs = RMATCH_REGS(rb_backref_get());
      if (start == end && BEG(0) == END(0)) {
-  if (!RSTRING_PTR(str)) {
+  if (!ptr) {
       rb_ary_push(result, rb_str_new("", 0));
       break;
   }
   else if (last_null == 1) {
       rb_ary_push(result, rb_str_subseq(str, beg,
-            rb_enc_fast_mbclen(RSTRING_PTR(str)+beg,
-          RSTRING_END(str),
+            rb_enc_fast_mbclen(ptr+beg,
+          ptr+len,
           enc)));
       beg = start;
   }
   else {
-                    if (RSTRING_PTR(str)+start == RSTRING_END(str))
+                    if (ptr+start == ptr+len)
                         start++;
                     else
-                        start += 
rb_enc_fast_mbclen(RSTRING_PTR(str)+start,RSTRING_END(str),enc);
+                        start += rb_enc_fast_mbclen(ptr+start,ptr+len,enc);
       last_null = 1;
       continue;
   }
--- struct.c (revision 25052)
+++ struct.c (working copy)
@@ -98,14 +98,17 @@
 VALUE
 rb_struct_getmember(VALUE obj, ID id)
 {
-    VALUE members, slot;
-    long i;
+    VALUE members, slot, *ptr, *ptr_members;
+    long i, len;

+    ptr = RSTRUCT_PTR(obj);
     members = rb_struct_members(obj);
+    ptr_members = RARRAY_PTR(members);
     slot = ID2SYM(id);
-    for (i=0; i<RARRAY_LEN(members); i++) {
- if (RARRAY_PTR(members)[i] == slot) {
-     return RSTRUCT_PTR(obj)[i];
+    len = RARRAY_LEN(members);
+    for (i=0; i<len; i++) {
+ if (ptr_members[i] == slot) {
+     return ptr[i];
  }
     }
     rb_name_error(id, "%s is not struct member", rb_id2name(id));
@@ -156,15 +159,18 @@
 static VALUE
 rb_struct_set(VALUE obj, VALUE val)
 {
-    VALUE members, slot;
-    long i;
+    VALUE members, slot, *ptr, *ptr_members;
+    long i, len;

     members = rb_struct_members(obj);
+    ptr_members = RARRAY_PTR(members);
+    len = RARRAY_LEN(members);
     rb_struct_modify(obj);
-    for (i=0; i<RARRAY_LEN(members); i++) {
- slot = RARRAY_PTR(members)[i];
+    ptr = RSTRUCT_PTR(obj);
+    for (i=0; i<len; i++) {
+ slot = ptr_members[i];
  if (rb_id_attrset(SYM2ID(slot)) == rb_frame_this_func()) {
-     return RSTRUCT_PTR(obj)[i] = val;
+     return ptr[i] = val;
  }
     }
     rb_name_error(rb_frame_this_func(), "`%s' is not a struct member",
@@ -175,9 +181,9 @@
 static VALUE
 make_struct(VALUE name, VALUE members, VALUE klass)
 {
-    VALUE nstr;
+    VALUE nstr, *ptr_members;
     ID id;
-    long i;
+    long i, len;

     OBJ_FREEZE(members);
     if (NIL_P(name)) {
@@ -204,8 +210,10 @@
     rb_define_singleton_method(nstr, "new", rb_class_new_instance, -1);
     rb_define_singleton_method(nstr, "[]", rb_class_new_instance, -1);
     rb_define_singleton_method(nstr, "members", rb_struct_s_members_m, 0);
-    for (i=0; i< RARRAY_LEN(members); i++) {
- ID id = SYM2ID(RARRAY_PTR(members)[i]);
+    ptr_members = RARRAY_PTR(members);
+    len = RARRAY_LEN(members);
+    for (i=0; i< len; i++) {
+ ID id = SYM2ID(ptr_members[i]);
  if (rb_is_local_id(id) || rb_is_const_id(id)) {
      if (i < N_REF_FUNC) {
   rb_define_method_id(nstr, id, ref_func[i], 0);
@@ -498,7 +506,8 @@
 {
     VALUE cname = rb_class_name(rb_obj_class(s));
     VALUE members, str = rb_str_new2("#<struct ");
-    long i;
+    VALUE *ptr, *ptr_members;
+    long i, len;
     char first = RSTRING_PTR(cname)[0];

     if (recur || first != '#') {
@@ -509,7 +518,10 @@
     }

     members = rb_struct_members(s);
-    for (i=0; i<RSTRUCT_LEN(s); i++) {
+    ptr_members = RARRAY_PTR(members);
+    ptr = RSTRUCT_PTR(s);
+    len = RSTRUCT_LEN(s);
+    for (i=0; i<len; i++) {
  VALUE slot;
  ID id;

@@ -519,7 +531,7 @@
  else if (first != '#') {
      rb_str_cat2(str, " ");
  }
- slot = RARRAY_PTR(members)[i];
+ slot = ptr_members[i];
  id = SYM2ID(slot);
  if (rb_is_local_id(id) || rb_is_const_id(id)) {
      rb_str_append(str, rb_id2str(id));
@@ -528,7 +540,7 @@
      rb_str_append(str, rb_inspect(slot));
  }
  rb_str_cat2(str, "=");
- rb_str_append(str, rb_inspect(RSTRUCT_PTR(s)[i]));
+ rb_str_append(str, rb_inspect(ptr[i]));
     }
     rb_str_cat2(str, ">");
     OBJ_INFECT(str, s);
@@ -588,14 +600,16 @@
 static VALUE
 rb_struct_aref_id(VALUE s, ID id)
 {
-    VALUE members;
+    VALUE *ptr, members, *ptr_members;
     long i, len;

+    ptr = RSTRUCT_PTR(s);
     members = rb_struct_members(s);
+    ptr_members = RARRAY_PTR(members);
     len = RARRAY_LEN(members);
     for (i=0; i<len; i++) {
- if (SYM2ID(RARRAY_PTR(members)[i]) == id) {
-     return RSTRUCT_PTR(s)[i];
+ if (SYM2ID(ptr_members[i]) == id) {
+     return ptr[i];
  }
     }
     rb_name_error(id, "no member '%s' in struct", rb_id2name(id));
@@ -644,19 +658,21 @@
 static VALUE
 rb_struct_aset_id(VALUE s, ID id, VALUE val)
 {
-    VALUE members;
+    VALUE members, *ptr, *ptr_members;
     long i, len;

     members = rb_struct_members(s);
-    rb_struct_modify(s);
     len = RARRAY_LEN(members);
-    if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) {
+    rb_struct_modify(s);
+    if (RSTRUCT_LEN(s) != len) {
  rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)",
-   RARRAY_LEN(members), RSTRUCT_LEN(s));
+   len, RSTRUCT_LEN(s));
     }
+    ptr = RSTRUCT_PTR(s);
+    ptr_members = RARRAY_PTR(members);
     for (i=0; i<len; i++) {
- if (SYM2ID(RARRAY_PTR(members)[i]) == id) {
-     RSTRUCT_PTR(s)[i] = val;
+ if (SYM2ID(ptr_members[i]) == id) {
+     ptr[i] = val;
      return val;
  }
     }
@@ -771,11 +787,15 @@
 static VALUE
 recursive_equal(VALUE s, VALUE s2, int recur)
 {
-    long i;
+    VALUE *ptr, *ptr2;
+    long i, len;

     if (recur) return Qtrue; /* Subtle! */
-    for (i=0; i<RSTRUCT_LEN(s); i++) {
- if (!rb_equal(RSTRUCT_PTR(s)[i], RSTRUCT_PTR(s2)[i])) return Qfalse;
+    ptr = RSTRUCT_PTR(s);
+    ptr2 = RSTRUCT_PTR(s2);
+    len = RSTRUCT_LEN(s);
+    for (i=0; i<len; i++) {
+ if (!rb_equal(ptr[i], ptr2[i])) return Qfalse;
     }
     return Qtrue;
 }
@@ -813,14 +833,16 @@
 static VALUE
 recursive_hash(VALUE s, VALUE dummy, int recur)
 {
-    long i;
+    long i, len;
     st_index_t h;
-    VALUE n;
+    VALUE n, *ptr;

     h = rb_hash_start(rb_hash(rb_obj_class(s)));
     if (!recur) {
- for (i = 0; i < RSTRUCT_LEN(s); i++) {
-     n = rb_hash(RSTRUCT_PTR(s)[i]);
+ ptr = RSTRUCT_PTR(s);
+ len = RSTRUCT_LEN(s);
+ for (i = 0; i < len; i++) {
+     n = rb_hash(ptr[i]);
      h = rb_hash_uint(h, NUM2LONG(n));
  }
     }
@@ -844,11 +866,15 @@
 static VALUE
 recursive_eql(VALUE s, VALUE s2, int recur)
 {
-    long i;
+    VALUE *ptr, *ptr2;
+    long i, len;

     if (recur) return Qtrue; /* Subtle! */
-    for (i=0; i<RSTRUCT_LEN(s); i++) {
- if (!rb_eql(RSTRUCT_PTR(s)[i], RSTRUCT_PTR(s2)[i])) return Qfalse;
+    ptr = RSTRUCT_PTR(s);
+    ptr2 = RSTRUCT_PTR(s2);
+    len = RSTRUCT_LEN(s);
+    for (i=0; i<len; i++) {
+ if (!rb_eql(ptr[i], ptr2[i])) return Qfalse;
     }
     return Qtrue;
 }

--
Masahiro Kanai (CanI)
http://d.hatena.ne.jp/CanI/