Bug #5254
closedclass オブジェクトの開放時に segv
Description
芝と申します。
次のようなコードを実行すると、gc の sweep フェーズで segv します。
再現コード¶
####################################
class BasicObject
def singleton_method_added(mid)
raise
end
end
b = proc {}
class << b; end
b.clone
####################################
b.clone では、class.c 内の rb_singleton_class_clone を呼び出し、class オ
ブジェクトの複製をします。このとき、class_alloc を呼び出して生の class
オブジェクトを割り当てるんですが、メソッドテーブルの割り当てを行う前に
singleton_method_added のコールバックを呼び出しています。このため、
singleton_method_added のコールバックで例外を吐いたときに、メソッドテー
ブルの割り当てが行われていない class オブジェクトが出来てしまっています。
obj_free では、class オブジェクトの開放時に、メソッドテーブルが割り当て
られているかどうかのチェック無しに、rb_free_m_table(RCLASS_M_TBL(obj));
とし、メソッドテーブルを開放しようとします。rb_free_m_table は、引数とし
てわたってくるハッシュテーブルが NULL ではないものとして処理を進めている
ため、上に記述したような、メソッドテーブルの割り当てが行われていない
class オブジェクトを開放しようとしたときに、segv を吐いてしまうようです。
obj_free からの呼び出し関係と segv の位置は次のような感じです。
obj_free
rb_free_m_table
st_foreach
if (table->entries_packed) { <= ここで segv
これに対する対処としては、rb_singleton_class_clone のメソッドテーブル初
期化の位置をずらすか、obj_free でメソッドテーブルの解放前にメソッドテー
ブルが割り当てられているかどうかのチェックをするかの2つがあります。
rb_singleton_class_clone のように、class オブジェクトの初期化とコール
バックの呼び出しを共に行うような処理が他に無いとも限らないので、obj_free
側に手を加えるのがいいと思います。本メール末尾にそのようなパッチを添付し
ておきます。
参考にしていただければ幸いです。
よろしくお願いいたします。
パッチ¶
Index: gc.c¶
--- gc.c (revision 33101)
+++ gc.c (working copy)
@@ -2273,7 +2273,9 @@
case T_MODULE:
case T_CLASS:
rb_clear_cache_by_class((VALUE)obj);
-
rb_free_m_table(RCLASS_M_TBL(obj));
-
if (RCLASS_M_TBL(obj)) {
-
rb_free_m_table(RCLASS_M_TBL(obj));
-
} if (RCLASS_IV_TBL(obj)) { st_free_table(RCLASS_IV_TBL(obj)); }
Updated by kosaki (Motohiro KOSAKI) over 13 years ago
- Subject changed from ] class オブジェクトの開放時に segv to class オブジェクトの開放時に segv
- Category set to core
- Status changed from Open to Assigned
- Assignee set to authorNari (Narihiro Nakamura)
- Target version set to 2.0.0
チケット化
Updated by authorNari (Narihiro Nakamura) over 12 years ago
- Status changed from Assigned to Closed
- % Done changed from 0 to 100
r35827 で修正しました。