mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-01-08 21:17:39 +03:00
Fix use-after-free with validating reader
Just like IDs, IDREF attributes must be removed from the document's refs table when they're freed by a reader. This bug is often hidden because xmlAttr structs are reused and strings are stored in a dictionary unless XML_PARSE_NODICT is specified. Found by OSS-Fuzz.
This commit is contained in:
parent
00ed736eec
commit
2af3c2a8b9
55
xmlreader.c
55
xmlreader.c
@ -278,6 +278,59 @@ xmlTextReaderRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlTextReaderWalkRemoveRef:
|
||||
* @data: Contents of current link
|
||||
* @user: Value supplied by the user
|
||||
*
|
||||
* Returns 0 to abort the walk or 1 to continue
|
||||
*/
|
||||
static int
|
||||
xmlTextReaderWalkRemoveRef(const void *data, void *user)
|
||||
{
|
||||
xmlRefPtr ref = (xmlRefPtr)data;
|
||||
xmlAttrPtr attr = (xmlAttrPtr)user;
|
||||
|
||||
if (ref->attr == attr) { /* Matched: remove and terminate walk */
|
||||
ref->name = xmlStrdup(attr->name);
|
||||
ref->attr = NULL;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlTextReaderRemoveRef:
|
||||
* @doc: the document
|
||||
* @attr: the attribute
|
||||
*
|
||||
* Remove the given attribute from the Ref table maintained internally.
|
||||
*
|
||||
* Returns -1 if the lookup failed and 0 otherwise
|
||||
*/
|
||||
static int
|
||||
xmlTextReaderRemoveRef(xmlDocPtr doc, xmlAttrPtr attr) {
|
||||
xmlListPtr ref_list;
|
||||
xmlRefTablePtr table;
|
||||
xmlChar *ID;
|
||||
|
||||
if (doc == NULL) return(-1);
|
||||
if (attr == NULL) return(-1);
|
||||
table = (xmlRefTablePtr) doc->refs;
|
||||
if (table == NULL)
|
||||
return(-1);
|
||||
|
||||
ID = xmlNodeListGetString(doc, attr->children, 1);
|
||||
if (ID == NULL)
|
||||
return(-1);
|
||||
ref_list = xmlHashLookup(table, ID);
|
||||
xmlFree(ID);
|
||||
if(ref_list == NULL)
|
||||
return (-1);
|
||||
xmlListWalk(ref_list, xmlTextReaderWalkRemoveRef, attr);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlTextReaderFreeProp:
|
||||
* @reader: the xmlTextReaderPtr used
|
||||
@ -304,6 +357,8 @@ xmlTextReaderFreeProp(xmlTextReaderPtr reader, xmlAttrPtr cur) {
|
||||
(cur->parent->doc->extSubset != NULL))) {
|
||||
if (xmlIsID(cur->parent->doc, cur->parent, cur))
|
||||
xmlTextReaderRemoveID(cur->parent->doc, cur);
|
||||
if (xmlIsRef(cur->parent->doc, cur->parent, cur))
|
||||
xmlTextReaderRemoveRef(cur->parent->doc, cur);
|
||||
}
|
||||
if (cur->children != NULL)
|
||||
xmlTextReaderFreeNodeList(reader, cur->children);
|
||||
|
Loading…
Reference in New Issue
Block a user