1From b1319c902f6e44d08f8cb33f1fc28847f2bc8aeb Mon Sep 17 00:00:00 2001 2From: Nick Wellnhofer <wellnhofer@aevum.de> 3Date: Sat, 18 Mar 2023 16:34:01 +0100 4Subject: [PATCH] malloc-fail: Check for malloc failures when creating XPath 5 strings 6 7Prevent null derefs. 8 9Found by OSS-Fuzz, see #344. 10 11Reference:https://github.com/GNOME/libxml2/commit/b1319c902f6e44d08f8cb33f1fc28847f2bc8aeb 12Conflict:xpath.c 13 14--- 15 xpath.c | 111 +++++++++++++++++++++----------------------------------- 16 1 file changed, 42 insertions(+), 69 deletions(-) 17 18diff --git a/xpath.c b/xpath.c 19index 005a6a2..2eceb5b 100644 20--- a/xpath.c 21+++ b/xpath.c 22@@ -2476,17 +2476,17 @@ xmlXPathCacheNewNodeSet(xmlXPathContextPtr ctxt, xmlNodePtr val) 23 } 24 25 /** 26- * xmlXPathCacheNewCString: 27+ * xmlXPathCacheNewString: 28 * @ctxt: the XPath context 29- * @val: the char * value 30+ * @val: the xmlChar * value 31 * 32- * This is the cached version of xmlXPathNewCString(). 33+ * This is the cached version of xmlXPathNewString(). 34 * Acquire an xmlXPathObjectPtr of type string and of value @val 35 * 36 * Returns the created or reused object. 37 */ 38 static xmlXPathObjectPtr 39-xmlXPathCacheNewCString(xmlXPathContextPtr ctxt, const char *val) 40+xmlXPathCacheNewString(xmlXPathContextPtr ctxt, const xmlChar *val) 41 { 42 if ((ctxt != NULL) && (ctxt->cache)) { 43 xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; 44@@ -2495,12 +2495,20 @@ xmlXPathCacheNewCString(xmlXPathContextPtr ctxt, const char *val) 45 (cache->stringObjs->number != 0)) 46 { 47 xmlXPathObjectPtr ret; 48+ xmlChar *copy; 49+ 50+ if (val == NULL) 51+ val = BAD_CAST ""; 52+ copy = xmlStrdup(val); 53+ if (copy == NULL) { 54+ xmlXPathErrMemory(ctxt, NULL); 55+ return(NULL); 56+ } 57 58 ret = (xmlXPathObjectPtr) 59 cache->stringObjs->items[--cache->stringObjs->number]; 60- 61 ret->type = XPATH_STRING; 62- ret->stringval = xmlStrdup(BAD_CAST val); 63+ ret->stringval = copy; 64 #ifdef XP_DEBUG_OBJ_USAGE 65 xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING); 66 #endif 67@@ -2509,73 +2517,44 @@ xmlXPathCacheNewCString(xmlXPathContextPtr ctxt, const char *val) 68 (cache->miscObjs->number != 0)) 69 { 70 xmlXPathObjectPtr ret; 71+ xmlChar *copy; 72+ 73+ if (val == NULL) 74+ val = BAD_CAST ""; 75+ copy = xmlStrdup(val); 76+ if (copy == NULL) { 77+ xmlXPathErrMemory(ctxt, NULL); 78+ return(NULL); 79+ } 80 81 ret = (xmlXPathObjectPtr) 82 cache->miscObjs->items[--cache->miscObjs->number]; 83 84 ret->type = XPATH_STRING; 85- ret->stringval = xmlStrdup(BAD_CAST val); 86+ ret->stringval = copy; 87 #ifdef XP_DEBUG_OBJ_USAGE 88 xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING); 89 #endif 90 return(ret); 91 } 92 } 93- return(xmlXPathNewCString(val)); 94+ return(xmlXPathNewString(val)); 95 } 96 97 /** 98- * xmlXPathCacheNewString: 99+ * xmlXPathCacheNewCString: 100 * @ctxt: the XPath context 101- * @val: the xmlChar * value 102+ * @val: the char * value 103 * 104- * This is the cached version of xmlXPathNewString(). 105+ * This is the cached version of xmlXPathNewCString(). 106 * Acquire an xmlXPathObjectPtr of type string and of value @val 107 * 108 * Returns the created or reused object. 109 */ 110 static xmlXPathObjectPtr 111-xmlXPathCacheNewString(xmlXPathContextPtr ctxt, const xmlChar *val) 112+xmlXPathCacheNewCString(xmlXPathContextPtr ctxt, const char *val) 113 { 114- if ((ctxt != NULL) && (ctxt->cache)) { 115- xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache; 116- 117- if ((cache->stringObjs != NULL) && 118- (cache->stringObjs->number != 0)) 119- { 120- xmlXPathObjectPtr ret; 121- 122- ret = (xmlXPathObjectPtr) 123- cache->stringObjs->items[--cache->stringObjs->number]; 124- ret->type = XPATH_STRING; 125- if (val != NULL) 126- ret->stringval = xmlStrdup(val); 127- else 128- ret->stringval = xmlStrdup((const xmlChar *)""); 129-#ifdef XP_DEBUG_OBJ_USAGE 130- xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING); 131-#endif 132- return(ret); 133- } else if ((cache->miscObjs != NULL) && 134- (cache->miscObjs->number != 0)) 135- { 136- xmlXPathObjectPtr ret; 137- 138- ret = (xmlXPathObjectPtr) 139- cache->miscObjs->items[--cache->miscObjs->number]; 140- 141- ret->type = XPATH_STRING; 142- if (val != NULL) 143- ret->stringval = xmlStrdup(val); 144- else 145- ret->stringval = xmlStrdup((const xmlChar *)""); 146-#ifdef XP_DEBUG_OBJ_USAGE 147- xmlXPathDebugObjUsageRequested(ctxt, XPATH_STRING); 148-#endif 149- return(ret); 150- } 151- } 152- return(xmlXPathNewString(val)); 153+ return xmlXPathCacheNewString(ctxt, BAD_CAST val); 154 } 155 156 /** 157@@ -5291,10 +5270,13 @@ xmlXPathNewString(const xmlChar *val) { 158 } 159 memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); 160 ret->type = XPATH_STRING; 161- if (val != NULL) 162- ret->stringval = xmlStrdup(val); 163- else 164- ret->stringval = xmlStrdup((const xmlChar *)""); 165+ if (val == NULL) 166+ val = BAD_CAST ""; 167+ ret->stringval = xmlStrdup(val); 168+ if (ret->stringval == NULL) { 169+ xmlFree(ret); 170+ return(NULL); 171+ } 172 #ifdef XP_DEBUG_OBJ_USAGE 173 xmlXPathDebugObjUsageRequested(NULL, XPATH_STRING); 174 #endif 175@@ -5340,20 +5322,7 @@ xmlXPathWrapString (xmlChar *val) { 176 */ 177 xmlXPathObjectPtr 178 xmlXPathNewCString(const char *val) { 179- xmlXPathObjectPtr ret; 180- 181- ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject)); 182- if (ret == NULL) { 183- xmlXPathErrMemory(NULL, "creating string object\n"); 184- return(NULL); 185- } 186- memset(ret, 0 , (size_t) sizeof(xmlXPathObject)); 187- ret->type = XPATH_STRING; 188- ret->stringval = xmlStrdup(BAD_CAST val); 189-#ifdef XP_DEBUG_OBJ_USAGE 190- xmlXPathDebugObjUsageRequested(NULL, XPATH_STRING); 191-#endif 192- return(ret); 193+ return(xmlXPathNewString(BAD_CAST val)); 194 } 195 196 /** 197@@ -5427,6 +5396,10 @@ xmlXPathObjectCopy(xmlXPathObjectPtr val) { 198 break; 199 case XPATH_STRING: 200 ret->stringval = xmlStrdup(val->stringval); 201+ if (ret->stringval == NULL) { 202+ xmlFree(ret); 203+ return(NULL); 204+ } 205 break; 206 case XPATH_XSLT_TREE: 207 #if 0 208-- 2092.27.0 210 211