Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean all occurrences of _private on GC when libxml-ruby is loaded. #895

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions ext/nokogiri/xml_document.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,47 @@ static int dealloc_node_i(xmlNodePtr key, xmlNodePtr node, xmlDocPtr doc)
return ST_CONTINUE;
}

static void remove_private(xmlNodePtr node)
{
xmlNodePtr child;

for (child = node->children; child; child = child->next)
remove_private(child);

if ((node->type == XML_ELEMENT_NODE ||
node->type == XML_XINCLUDE_START ||
node->type == XML_XINCLUDE_END) &&
node->properties) {
for (child = (xmlNodePtr)node->properties; child; child = child->next)
remove_private(child);
}

node->_private = NULL;
}

static void dealloc(xmlDocPtr doc)
{
xmlDeregisterNodeFunc func;
st_table *node_hash;

NOKOGIRI_DEBUG_START(doc);
func = xmlDeregisterNodeDefault(NULL);

node_hash = DOC_UNLINKED_NODE_HASH(doc);

st_foreach(node_hash, dealloc_node_i, (st_data_t)doc);
st_free_table(node_hash);

free(doc->_private);
doc->_private = NULL;

/* When both Nokogiri and libxml-ruby are loaded, make sure that all nodes
* have their _private pointers cleared. This is to avoid libxml-ruby's
* xmlDeregisterNode callback from accessing VALUE pointers from ruby's GC
* free context, which can result in segfaults.
*/
if (xmlDeregisterNodeDefaultValue)
remove_private((xmlNodePtr)doc);

xmlFreeDoc(doc);

xmlDeregisterNodeDefault(func);
NOKOGIRI_DEBUG_END(doc);
}

Expand Down