Bug #5255

C の Proc の比較のバグ

Added by Anonymous over 3 years ago. Updated over 3 years ago.

[ruby-dev:44435]
Status:Closed
Priority:Normal
Assignee:-
ruby -v:uby 1.9.3dev (2011-08-02 revision 32810) [i686-linux] Backport:

Description

芝と申します。

Proc#eq(C の関数は proc.c 内の proc_eq)で、C で定義した Proc
(rb_proc_new などを用いて定義)の比較を行う箇所に不具合があります。
C で定義した Proc に対しても iseq を見て比較を行っているため、メモリの状
況如何で segv を吐いたり false のはずが true になったりします。

問題となる proc_eq は以下のようになっていて、Proc の種類にかかわらず、
proc->block.iseq->iseq_size, proc->block.iseq->local_size,
proc->block.iseq->iseq を用いて比較しています。
proc->block.iseq が IFUNC_NODE だった場合は、関数ポインタの比較など、別
の方法で比較を行うべきです。

/* 問題の関数 */
static VALUE
proc_eq(VALUE self, VALUE other)
{
if (self == other) {
return Qtrue;
}
else {
if (rb_obj_is_proc(other)) {
rb_proc_t *p1, *p2;
GetProcPtr(self, p1);
GetProcPtr(other, p2);
if (p1->envval == p2->envval &&
p1->block.iseq->iseq_size == p2->block.iseq->iseq_size &&
p1->block.iseq->local_size == p2->block.iseq->local_size &&
MEMCMP(p1->block.iseq->iseq, p2->block.iseq->iseq, VALUE,
p1->block.iseq->iseq_size) == 0) {
return Qtrue;
}
}
}
return Qfalse;
}

添付する sample.zip に、proc_eq に対するパッチと問題となるコードの例をま
とめて入れておきます。
今回のパッチでは、RUBY_VM_IFUNC_P で C の Proc かどうかを判定し、proc 2
つが共に C の Proc だった場合は、node->nd_cfnc, node->nd_aid,
node->nd_tval で比較します。

参考にしていただければ幸いです。
よろしくお願いいたします。

/* パッチ */
diff --git proc.c proc.c
index 427d1fe..e304295 100644
--- proc.c
+++ proc.c
@@ -766,7 +766,18 @@ proc_eq(VALUE self, VALUE other)
rb_proc_t *p1, *p2;
GetProcPtr(self, p1);
GetProcPtr(other, p2);
- if (p1->envval == p2->envval &&
+ if (RUBY_VM_IFUNC_P(p1->block.iseq) &&
RUBY_VM_IFUNC_P(p2->block.iseq)) {
+ NODE *nd_ifunc1, *nd_ifunc2;
+
+ nd_ifunc1 = (NODE *)p1->block.iseq;
+ nd_ifunc2 = (NODE *)p2->block.iseq;
+ if(nd_ifunc1->nd_cfnc == nd_ifunc2->nd_cfnc &&
+ nd_ifunc1->nd_aid == nd_ifunc2->nd_aid &&
+ rb_funcall(nd_ifunc1->nd_tval, idEq, 1,
nd_ifunc2->nd_tval)) {
+ return Qtrue;
+ }
+ } else if (p1->envval == p2->envval &&
+ !RUBY_VM_IFUNC_P(p1->block.iseq) &&
!RUBY_VM_IFUNC_P(p2->block.iseq) &&
p1->block.iseq->iseq_size == p2->block.iseq->iseq_size &&
p1->block.iseq->local_size == p2->block.iseq->local_size &&
MEMCMP(p1->block.iseq->iseq, p2->block.iseq->iseq, VALUE,

sample.zip (1.18 KB) Anonymous, 09/01/2011 09:15 AM


Related issues

Duplicates Ruby trunk - Bug #5249: C の Proc の比較のバグ Closed

History

#1 Updated by Motohiro KOSAKI over 3 years ago

  • Subject changed from ] C $B$N(B Proc $B$NHf3S$N%P%0(B to C の Proc の比較のバグ
  • Category set to core
  • Target version set to 2.0.0
  • ruby -v changed from - to uby 1.9.3dev (2011-08-02 revision 32810) [i686-linux]

をチケット化

#2 Updated by Motohiro KOSAKI over 3 years ago

  • Status changed from Open to Closed

すいません。 #5249ですでにチケット化ずみでした。closeします

Also available in: Atom PDF