From a1b7f1eef74ac9d69900488a56ba96ae9144615d Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Tue, 14 Feb 2012 14:17:43 -0800 Subject: xml_node: hack to avoid marking invalid object *** I don't understand why this patch works *** *** I don't understand why this patch works *** *** I don't understand why this patch works *** By using an ivar instead of a custom mark method, this seems to prevent a bad object from being marked. I've been running this on setups that would've triggered this SEGV much sooner. This change seems to fix: https://github.com/tenderlove/nokogiri/issues/616 This patch may also have a negative performance impact, I haven't benchmarked. *** I don't understand why this patch works *** *** I don't understand why this patch works *** *** I don't understand why this patch works *** --- ext/nokogiri/xml_node.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/ext/nokogiri/xml_node.c b/ext/nokogiri/xml_node.c index df1bcebc..b04e3fc6 100644 --- a/ext/nokogiri/xml_node.c +++ b/ext/nokogiri/xml_node.c @@ -1,6 +1,6 @@ #include -static ID decorate, decorate_bang; +static ID decorate, decorate_bang, debug_document; #ifdef DEBUG static void debug_node_dealloc(xmlNodePtr x) @@ -12,11 +12,6 @@ static void debug_node_dealloc(xmlNodePtr x) # define debug_node_dealloc 0 #endif -static void mark(xmlNodePtr node) -{ - rb_gc_mark(DOC_RUBY_OBJECT(node->doc)); -} - /* :nodoc: */ typedef xmlNodePtr (*pivot_reparentee_func)(xmlNodePtr, xmlNodePtr); @@ -1303,7 +1298,6 @@ VALUE Nokogiri_wrap_xml_node(VALUE klass, xmlNodePtr node) VALUE node_cache = Qnil ; VALUE rb_node = Qnil ; nokogiriTuplePtr node_has_a_document; - void (*mark_method)(xmlNodePtr) = NULL ; assert(node); @@ -1362,13 +1356,12 @@ VALUE Nokogiri_wrap_xml_node(VALUE klass, xmlNodePtr node) } } - mark_method = node_has_a_document ? mark : NULL ; - - rb_node = Data_Wrap_Struct(klass, mark_method, debug_node_dealloc, node) ; + rb_node = Data_Wrap_Struct(klass, NULL, debug_node_dealloc, node) ; node->_private = (void *)rb_node; if (node_has_a_document) { document = DOC_RUBY_OBJECT(node->doc); + rb_ivar_set(rb_node, debug_document, document); node_cache = DOC_NODE_CACHE(node->doc); rb_ary_push(node_cache, rb_node); rb_funcall(document, decorate, 1, rb_node); @@ -1455,4 +1448,5 @@ void init_xml_node() decorate = rb_intern("decorate"); decorate_bang = rb_intern("decorate!"); + debug_document = rb_intern("@debug_document"); } -- cgit v1.2.3-24-ge0c7