1From cde95d801abc9405ca821ad814c7730333328d96 Mon Sep 17 00:00:00 2001 2From: Nick Wellnhofer <wellnhofer@aevum.de> 3Date: Wed, 31 Aug 2022 22:11:25 +0200 4Subject: [PATCH] CVE-2022-40304 5 6Fix dict corruption caused by entity reference cycles 7 8When an entity reference cycle is detected, the entity content is 9cleared by setting its first byte to zero. But the entity content might 10be allocated from a dict. In this case, the dict entry becomes corrupted 11leading to all kinds of logic errors, including memory errors like 12double-frees. 13 14Stop storing entity content, orig, ExternalID and SystemID in a dict. 15These values are unlikely to occur multiple times in a document, so they 16shouldn't have been stored in a dict in the first place. 17 18Thanks to Ned Williamson and Nathan Wachholz working with Google Project 19Zero for the report! 20 21Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/1b41ec4e9433b05bb0376be4725804c54ef1d80b] 22CVE: CVE-2022-40304 23Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com> 24--- 25 entities.c | 55 ++++++++++++++++-------------------------------------- 26 1 file changed, 16 insertions(+), 39 deletions(-) 27 28diff --git a/entities.c b/entities.c 29index 1a8f86f..ec1b9a7 100644 30--- a/entities.c 31+++ b/entities.c 32@@ -112,36 +112,19 @@ xmlFreeEntity(xmlEntityPtr entity) 33 if ((entity->children) && (entity->owner == 1) && 34 (entity == (xmlEntityPtr) entity->children->parent)) 35 xmlFreeNodeList(entity->children); 36- if (dict != NULL) { 37- if ((entity->name != NULL) && (!xmlDictOwns(dict, entity->name))) 38- xmlFree((char *) entity->name); 39- if ((entity->ExternalID != NULL) && 40- (!xmlDictOwns(dict, entity->ExternalID))) 41- xmlFree((char *) entity->ExternalID); 42- if ((entity->SystemID != NULL) && 43- (!xmlDictOwns(dict, entity->SystemID))) 44- xmlFree((char *) entity->SystemID); 45- if ((entity->URI != NULL) && (!xmlDictOwns(dict, entity->URI))) 46- xmlFree((char *) entity->URI); 47- if ((entity->content != NULL) 48- && (!xmlDictOwns(dict, entity->content))) 49- xmlFree((char *) entity->content); 50- if ((entity->orig != NULL) && (!xmlDictOwns(dict, entity->orig))) 51- xmlFree((char *) entity->orig); 52- } else { 53- if (entity->name != NULL) 54- xmlFree((char *) entity->name); 55- if (entity->ExternalID != NULL) 56- xmlFree((char *) entity->ExternalID); 57- if (entity->SystemID != NULL) 58- xmlFree((char *) entity->SystemID); 59- if (entity->URI != NULL) 60- xmlFree((char *) entity->URI); 61- if (entity->content != NULL) 62- xmlFree((char *) entity->content); 63- if (entity->orig != NULL) 64- xmlFree((char *) entity->orig); 65- } 66+ if ((entity->name != NULL) && 67+ ((dict == NULL) || (!xmlDictOwns(dict, entity->name)))) 68+ xmlFree((char *) entity->name); 69+ if (entity->ExternalID != NULL) 70+ xmlFree((char *) entity->ExternalID); 71+ if (entity->SystemID != NULL) 72+ xmlFree((char *) entity->SystemID); 73+ if (entity->URI != NULL) 74+ xmlFree((char *) entity->URI); 75+ if (entity->content != NULL) 76+ xmlFree((char *) entity->content); 77+ if (entity->orig != NULL) 78+ xmlFree((char *) entity->orig); 79 xmlFree(entity); 80 } 81 82@@ -177,18 +160,12 @@ xmlCreateEntity(xmlDictPtr dict, const xmlChar *name, int type, 83 ret->SystemID = xmlStrdup(SystemID); 84 } else { 85 ret->name = xmlDictLookup(dict, name, -1); 86- if (ExternalID != NULL) 87- ret->ExternalID = xmlDictLookup(dict, ExternalID, -1); 88- if (SystemID != NULL) 89- ret->SystemID = xmlDictLookup(dict, SystemID, -1); 90+ ret->ExternalID = xmlStrdup(ExternalID); 91+ ret->SystemID = xmlStrdup(SystemID); 92 } 93 if (content != NULL) { 94 ret->length = xmlStrlen(content); 95- if ((dict != NULL) && (ret->length < 5)) 96- ret->content = (xmlChar *) 97- xmlDictLookup(dict, content, ret->length); 98- else 99- ret->content = xmlStrndup(content, ret->length); 100+ ret->content = xmlStrndup(content, ret->length); 101 } else { 102 ret->length = 0; 103 ret->content = NULL; 104-- 1052.25.1 106 107