diff options
Diffstat (limited to 'meta/recipes-core/libxml/libxml2')
20 files changed, 3025 insertions, 0 deletions
diff --git a/meta/recipes-core/libxml/libxml2/0001-Port-gentest.py-to-Python-3.patch b/meta/recipes-core/libxml/libxml2/0001-Port-gentest.py-to-Python-3.patch new file mode 100644 index 0000000000..b0d26d1c08 --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/0001-Port-gentest.py-to-Python-3.patch @@ -0,0 +1,813 @@ +From b5125000917810731bc28055c0445d571121f80e Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Thu, 21 Apr 2022 00:45:58 +0200 +Subject: [PATCH] Port gentest.py to Python 3 + +Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/343fc1421cdae097fa6c4cffeb1a065a40be6bbb] + +* fixes: + +make[1]: 'testReader' is up to date. + File "../libxml2-2.9.10/gentest.py", line 11 + print "libxml2 python bindings not available, skipping testapi.c generation" + ^ +SyntaxError: Missing parentheses in call to 'print'. Did you mean print("libxml2 python bindings not available, skipping testapi.c generation")? +make[1]: [Makefile:2078: testapi.c] Error 1 (ignored) + +... + +make[1]: 'testReader' is up to date. + File "../libxml2-2.9.10/gentest.py", line 271 + return 1 + ^ +TabError: inconsistent use of tabs and spaces in indentation +make[1]: [Makefile:2078: testapi.c] Error 1 (ignored) + +... + +aarch64-oe-linux-gcc: error: testapi.c: No such file or directory +aarch64-oe-linux-gcc: fatal error: no input files +compilation terminated. +make[1]: *** [Makefile:1275: testapi.o] Error 1 + +But there is still a bit mystery why it worked before, because check-am +calls gentest.py with $(PYTHON), so it ignores the shebang in the script +and libxml2 is using python3native (through python3targetconfig.bbclass) +so something like: + +libxml2/2.9.10-r0/recipe-sysroot-native/usr/bin/python3-native/python3 gentest.py + +But that still fails (now without SyntaxError) with: +libxml2 python bindings not available, skipping testapi.c generation + +because we don't have dependency on libxml2-native (to provide libxml2 +python bindings form python3native) and exported PYTHON_SITE_PACKAGES +might be useless (e.g. /usr/lib/python3.8/site-packages on Ubuntu-22.10 +which uses python 3.10 and there is no site-packages with libxml2) + +Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com> +--- + gentest.py | 421 ++++++++++++++++++++++++++--------------------------- + 1 file changed, 209 insertions(+), 212 deletions(-) + +diff --git a/gentest.py b/gentest.py +index b763300..0756706 100755 +--- a/gentest.py ++++ b/gentest.py +@@ -8,7 +8,7 @@ import string + try: + import libxml2 + except: +- print "libxml2 python bindings not available, skipping testapi.c generation" ++ print("libxml2 python bindings not available, skipping testapi.c generation") + sys.exit(0) + + if len(sys.argv) > 1: +@@ -227,7 +227,7 @@ extra_post_call = { + if (old != NULL) { + xmlUnlinkNode(old); + xmlFreeNode(old) ; old = NULL ; } +- ret_val = NULL;""", ++\t ret_val = NULL;""", + "xmlTextMerge": + """if ((first != NULL) && (first->type != XML_TEXT_NODE)) { + xmlUnlinkNode(second); +@@ -236,7 +236,7 @@ extra_post_call = { + """if ((ret_val != NULL) && (ret_val != ncname) && + (ret_val != prefix) && (ret_val != memory)) + xmlFree(ret_val); +- ret_val = NULL;""", ++\t ret_val = NULL;""", + "xmlNewDocElementContent": + """xmlFreeDocElementContent(doc, ret_val); ret_val = NULL;""", + "xmlDictReference": "xmlDictFree(dict);", +@@ -268,29 +268,29 @@ modules = [] + def is_skipped_module(name): + for mod in skipped_modules: + if mod == name: +- return 1 ++ return 1 + return 0 + + def is_skipped_function(name): + for fun in skipped_functions: + if fun == name: +- return 1 ++ return 1 + # Do not test destructors +- if string.find(name, 'Free') != -1: ++ if name.find('Free') != -1: + return 1 + return 0 + + def is_skipped_memcheck(name): + for fun in skipped_memcheck: + if fun == name: +- return 1 ++ return 1 + return 0 + + missing_types = {} + def add_missing_type(name, func): + try: + list = missing_types[name] +- list.append(func) ++ list.append(func) + except: + missing_types[name] = [func] + +@@ -310,7 +310,7 @@ def add_missing_functions(name, module): + missing_functions_nr = missing_functions_nr + 1 + try: + list = missing_functions[module] +- list.append(name) ++ list.append(name) + except: + missing_functions[module] = [name] + +@@ -319,45 +319,45 @@ def add_missing_functions(name, module): + # + + def type_convert(str, name, info, module, function, pos): +-# res = string.replace(str, " ", " ") +-# res = string.replace(str, " ", " ") +-# res = string.replace(str, " ", " ") +- res = string.replace(str, " *", "_ptr") +-# res = string.replace(str, "*", "_ptr") +- res = string.replace(res, " ", "_") ++# res = str.replace(" ", " ") ++# res = str.replace(" ", " ") ++# res = str.replace(" ", " ") ++ res = str.replace(" *", "_ptr") ++# res = str.replace("*", "_ptr") ++ res = res.replace(" ", "_") + if res == 'const_char_ptr': +- if string.find(name, "file") != -1 or \ +- string.find(name, "uri") != -1 or \ +- string.find(name, "URI") != -1 or \ +- string.find(info, "filename") != -1 or \ +- string.find(info, "URI") != -1 or \ +- string.find(info, "URL") != -1: +- if string.find(function, "Save") != -1 or \ +- string.find(function, "Create") != -1 or \ +- string.find(function, "Write") != -1 or \ +- string.find(function, "Fetch") != -1: +- return('fileoutput') +- return('filepath') ++ if name.find("file") != -1 or \ ++ name.find("uri") != -1 or \ ++ name.find("URI") != -1 or \ ++ info.find("filename") != -1 or \ ++ info.find("URI") != -1 or \ ++ info.find("URL") != -1: ++ if function.find("Save") != -1 or \ ++ function.find("Create") != -1 or \ ++ function.find("Write") != -1 or \ ++ function.find("Fetch") != -1: ++ return('fileoutput') ++ return('filepath') + if res == 'void_ptr': + if module == 'nanoftp' and name == 'ctx': +- return('xmlNanoFTPCtxtPtr') ++ return('xmlNanoFTPCtxtPtr') + if function == 'xmlNanoFTPNewCtxt' or \ +- function == 'xmlNanoFTPConnectTo' or \ +- function == 'xmlNanoFTPOpen': +- return('xmlNanoFTPCtxtPtr') ++ function == 'xmlNanoFTPConnectTo' or \ ++ function == 'xmlNanoFTPOpen': ++ return('xmlNanoFTPCtxtPtr') + if module == 'nanohttp' and name == 'ctx': +- return('xmlNanoHTTPCtxtPtr') +- if function == 'xmlNanoHTTPMethod' or \ +- function == 'xmlNanoHTTPMethodRedir' or \ +- function == 'xmlNanoHTTPOpen' or \ +- function == 'xmlNanoHTTPOpenRedir': +- return('xmlNanoHTTPCtxtPtr'); ++ return('xmlNanoHTTPCtxtPtr') ++ if function == 'xmlNanoHTTPMethod' or \ ++ function == 'xmlNanoHTTPMethodRedir' or \ ++ function == 'xmlNanoHTTPOpen' or \ ++ function == 'xmlNanoHTTPOpenRedir': ++ return('xmlNanoHTTPCtxtPtr'); + if function == 'xmlIOHTTPOpen': +- return('xmlNanoHTTPCtxtPtr') +- if string.find(name, "data") != -1: +- return('userdata') +- if string.find(name, "user") != -1: +- return('userdata') ++ return('xmlNanoHTTPCtxtPtr') ++ if name.find("data") != -1: ++ return('userdata') ++ if name.find("user") != -1: ++ return('userdata') + if res == 'xmlDoc_ptr': + res = 'xmlDocPtr' + if res == 'xmlNode_ptr': +@@ -366,18 +366,18 @@ def type_convert(str, name, info, module, function, pos): + res = 'xmlDictPtr' + if res == 'xmlNodePtr' and pos != 0: + if (function == 'xmlAddChild' and pos == 2) or \ +- (function == 'xmlAddChildList' and pos == 2) or \ ++ (function == 'xmlAddChildList' and pos == 2) or \ + (function == 'xmlAddNextSibling' and pos == 2) or \ + (function == 'xmlAddSibling' and pos == 2) or \ + (function == 'xmlDocSetRootElement' and pos == 2) or \ + (function == 'xmlReplaceNode' and pos == 2) or \ + (function == 'xmlTextMerge') or \ +- (function == 'xmlAddPrevSibling' and pos == 2): +- return('xmlNodePtr_in'); ++ (function == 'xmlAddPrevSibling' and pos == 2): ++ return('xmlNodePtr_in'); + if res == 'const xmlBufferPtr': + res = 'xmlBufferPtr' + if res == 'xmlChar_ptr' and name == 'name' and \ +- string.find(function, "EatName") != -1: ++ function.find("EatName") != -1: + return('eaten_name') + if res == 'void_ptr*': + res = 'void_ptr_ptr' +@@ -393,7 +393,7 @@ def type_convert(str, name, info, module, function, pos): + res = 'debug_FILE_ptr'; + if res == 'int' and name == 'options': + if module == 'parser' or module == 'xmlreader': +- res = 'parseroptions' ++ res = 'parseroptions' + + return res + +@@ -402,28 +402,28 @@ known_param_types = [] + def is_known_param_type(name): + for type in known_param_types: + if type == name: +- return 1 ++ return 1 + return name[-3:] == 'Ptr' or name[-4:] == '_ptr' + + def generate_param_type(name, rtype): + global test + for type in known_param_types: + if type == name: +- return ++ return + for type in generated_param_types: + if type == name: +- return ++ return + + if name[-3:] == 'Ptr' or name[-4:] == '_ptr': + if rtype[0:6] == 'const ': +- crtype = rtype[6:] +- else: +- crtype = rtype ++ crtype = rtype[6:] ++ else: ++ crtype = rtype + + define = 0 +- if modules_defines.has_key(module): +- test.write("#ifdef %s\n" % (modules_defines[module])) +- define = 1 ++ if module in modules_defines: ++ test.write("#ifdef %s\n" % (modules_defines[module])) ++ define = 1 + test.write(""" + #define gen_nb_%s 1 + static %s gen_%s(int no ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) { +@@ -433,7 +433,7 @@ static void des_%s(int no ATTRIBUTE_UNUSED, %s val ATTRIBUTE_UNUSED, int nr ATTR + } + """ % (name, crtype, name, name, rtype)) + if define == 1: +- test.write("#endif\n\n") ++ test.write("#endif\n\n") + add_generated_param_type(name) + + # +@@ -445,7 +445,7 @@ known_return_types = [] + def is_known_return_type(name): + for type in known_return_types: + if type == name: +- return 1 ++ return 1 + return 0 + + # +@@ -471,7 +471,7 @@ def compare_and_save(): + try: + os.system("rm testapi.c; mv testapi.c.new testapi.c") + except: +- os.system("mv testapi.c.new testapi.c") ++ os.system("mv testapi.c.new testapi.c") + print("Updated testapi.c") + else: + print("Generated testapi.c is identical") +@@ -481,17 +481,17 @@ while line != "": + if line == "/* CUT HERE: everything below that line is generated */\n": + break; + if line[0:15] == "#define gen_nb_": +- type = string.split(line[15:])[0] +- known_param_types.append(type) ++ type = line[15:].split()[0] ++ known_param_types.append(type) + if line[0:19] == "static void desret_": +- type = string.split(line[19:], '(')[0] +- known_return_types.append(type) ++ type = line[19:].split('(')[0] ++ known_return_types.append(type) + test.write(line) + line = input.readline() + input.close() + + if line == "": +- print "Could not find the CUT marker in testapi.c skipping generation" ++ print("Could not find the CUT marker in testapi.c skipping generation") + test.close() + sys.exit(0) + +@@ -505,7 +505,7 @@ test.write("/* CUT HERE: everything below that line is generated */\n") + # + doc = libxml2.readFile(srcPref + 'doc/libxml2-api.xml', None, 0) + if doc == None: +- print "Failed to load doc/libxml2-api.xml" ++ print("Failed to load doc/libxml2-api.xml") + sys.exit(1) + ctxt = doc.xpathNewContext() + +@@ -519,9 +519,9 @@ for arg in args: + mod = arg.xpathEval('string(../@file)') + func = arg.xpathEval('string(../@name)') + if (mod not in skipped_modules) and (func not in skipped_functions): +- type = arg.xpathEval('string(@type)') +- if not argtypes.has_key(type): +- argtypes[type] = func ++ type = arg.xpathEval('string(@type)') ++ if type not in argtypes: ++ argtypes[type] = func + + # similarly for return types + rettypes = {} +@@ -531,8 +531,8 @@ for ret in rets: + func = ret.xpathEval('string(../@name)') + if (mod not in skipped_modules) and (func not in skipped_functions): + type = ret.xpathEval('string(@type)') +- if not rettypes.has_key(type): +- rettypes[type] = func ++ if type not in rettypes: ++ rettypes[type] = func + + # + # Generate constructors and return type handling for all enums +@@ -549,49 +549,49 @@ for enum in enums: + continue; + define = 0 + +- if argtypes.has_key(name) and is_known_param_type(name) == 0: +- values = ctxt.xpathEval("/api/symbols/enum[@type='%s']" % name) +- i = 0 +- vals = [] +- for value in values: +- vname = value.xpathEval('string(@name)') +- if vname == None: +- continue; +- i = i + 1 +- if i >= 5: +- break; +- vals.append(vname) +- if vals == []: +- print "Didn't find any value for enum %s" % (name) +- continue +- if modules_defines.has_key(module): +- test.write("#ifdef %s\n" % (modules_defines[module])) +- define = 1 +- test.write("#define gen_nb_%s %d\n" % (name, len(vals))) +- test.write("""static %s gen_%s(int no, int nr ATTRIBUTE_UNUSED) {\n""" % +- (name, name)) +- i = 1 +- for value in vals: +- test.write(" if (no == %d) return(%s);\n" % (i, value)) +- i = i + 1 +- test.write(""" return(0); ++ if (name in argtypes) and is_known_param_type(name) == 0: ++ values = ctxt.xpathEval("/api/symbols/enum[@type='%s']" % name) ++ i = 0 ++ vals = [] ++ for value in values: ++ vname = value.xpathEval('string(@name)') ++ if vname == None: ++ continue; ++ i = i + 1 ++ if i >= 5: ++ break; ++ vals.append(vname) ++ if vals == []: ++ print("Didn't find any value for enum %s" % (name)) ++ continue ++ if module in modules_defines: ++ test.write("#ifdef %s\n" % (modules_defines[module])) ++ define = 1 ++ test.write("#define gen_nb_%s %d\n" % (name, len(vals))) ++ test.write("""static %s gen_%s(int no, int nr ATTRIBUTE_UNUSED) {\n""" % ++ (name, name)) ++ i = 1 ++ for value in vals: ++ test.write(" if (no == %d) return(%s);\n" % (i, value)) ++ i = i + 1 ++ test.write(""" return(0); + } + + static void des_%s(int no ATTRIBUTE_UNUSED, %s val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) { + } + + """ % (name, name)); +- known_param_types.append(name) ++ known_param_types.append(name) + + if (is_known_return_type(name) == 0) and (name in rettypes): +- if define == 0 and modules_defines.has_key(module): +- test.write("#ifdef %s\n" % (modules_defines[module])) +- define = 1 ++ if define == 0 and (module in modules_defines): ++ test.write("#ifdef %s\n" % (modules_defines[module])) ++ define = 1 + test.write("""static void desret_%s(%s val ATTRIBUTE_UNUSED) { + } + + """ % (name, name)) +- known_return_types.append(name) ++ known_return_types.append(name) + if define == 1: + test.write("#endif\n\n") + +@@ -615,9 +615,9 @@ for file in headers: + # do not test deprecated APIs + # + desc = file.xpathEval('string(description)') +- if string.find(desc, 'DEPRECATED') != -1: +- print "Skipping deprecated interface %s" % name +- continue; ++ if desc.find('DEPRECATED') != -1: ++ print("Skipping deprecated interface %s" % name) ++ continue; + + test.write("#include <libxml/%s.h>\n" % name) + modules.append(name) +@@ -679,7 +679,7 @@ def generate_test(module, node): + # and store the informations for the generation + # + try: +- args = node.xpathEval("arg") ++ args = node.xpathEval("arg") + except: + args = [] + t_args = [] +@@ -687,37 +687,37 @@ def generate_test(module, node): + for arg in args: + n = n + 1 + rtype = arg.xpathEval("string(@type)") +- if rtype == 'void': +- break; +- info = arg.xpathEval("string(@info)") +- nam = arg.xpathEval("string(@name)") ++ if rtype == 'void': ++ break; ++ info = arg.xpathEval("string(@info)") ++ nam = arg.xpathEval("string(@name)") + type = type_convert(rtype, nam, info, module, name, n) +- if is_known_param_type(type) == 0: +- add_missing_type(type, name); +- no_gen = 1 ++ if is_known_param_type(type) == 0: ++ add_missing_type(type, name); ++ no_gen = 1 + if (type[-3:] == 'Ptr' or type[-4:] == '_ptr') and \ +- rtype[0:6] == 'const ': +- crtype = rtype[6:] +- else: +- crtype = rtype +- t_args.append((nam, type, rtype, crtype, info)) ++ rtype[0:6] == 'const ': ++ crtype = rtype[6:] ++ else: ++ crtype = rtype ++ t_args.append((nam, type, rtype, crtype, info)) + + try: +- rets = node.xpathEval("return") ++ rets = node.xpathEval("return") + except: + rets = [] + t_ret = None + for ret in rets: + rtype = ret.xpathEval("string(@type)") +- info = ret.xpathEval("string(@info)") ++ info = ret.xpathEval("string(@info)") + type = type_convert(rtype, 'return', info, module, name, 0) +- if rtype == 'void': +- break +- if is_known_return_type(type) == 0: +- add_missing_type(type, name); +- no_gen = 1 +- t_ret = (type, rtype, info) +- break ++ if rtype == 'void': ++ break ++ if is_known_return_type(type) == 0: ++ add_missing_type(type, name); ++ no_gen = 1 ++ t_ret = (type, rtype, info) ++ break + + if no_gen == 0: + for t_arg in t_args: +@@ -733,7 +733,7 @@ test_%s(void) { + + if no_gen == 1: + add_missing_functions(name, module) +- test.write(""" ++ test.write(""" + /* missing type support */ + return(test_ret); + } +@@ -742,22 +742,22 @@ test_%s(void) { + return + + try: +- conds = node.xpathEval("cond") +- for cond in conds: +- test.write("#if %s\n" % (cond.get_content())) +- nb_cond = nb_cond + 1 ++ conds = node.xpathEval("cond") ++ for cond in conds: ++ test.write("#if %s\n" % (cond.get_content())) ++ nb_cond = nb_cond + 1 + except: + pass + + define = 0 +- if function_defines.has_key(name): ++ if name in function_defines: + test.write("#ifdef %s\n" % (function_defines[name])) +- define = 1 ++ define = 1 + + # Declare the memory usage counter + no_mem = is_skipped_memcheck(name) + if no_mem == 0: +- test.write(" int mem_base;\n"); ++ test.write(" int mem_base;\n"); + + # Declare the return value + if t_ret != None: +@@ -766,29 +766,29 @@ test_%s(void) { + # Declare the arguments + for arg in t_args: + (nam, type, rtype, crtype, info) = arg; +- # add declaration +- test.write(" %s %s; /* %s */\n" % (crtype, nam, info)) +- test.write(" int n_%s;\n" % (nam)) ++ # add declaration ++ test.write(" %s %s; /* %s */\n" % (crtype, nam, info)) ++ test.write(" int n_%s;\n" % (nam)) + test.write("\n") + + # Cascade loop on of each argument list of values + for arg in t_args: + (nam, type, rtype, crtype, info) = arg; +- # +- test.write(" for (n_%s = 0;n_%s < gen_nb_%s;n_%s++) {\n" % ( +- nam, nam, type, nam)) ++ # ++ test.write(" for (n_%s = 0;n_%s < gen_nb_%s;n_%s++) {\n" % ( ++ nam, nam, type, nam)) + + # log the memory usage + if no_mem == 0: +- test.write(" mem_base = xmlMemBlocks();\n"); ++ test.write(" mem_base = xmlMemBlocks();\n"); + + # prepare the call + i = 0; + for arg in t_args: + (nam, type, rtype, crtype, info) = arg; +- # +- test.write(" %s = gen_%s(n_%s, %d);\n" % (nam, type, nam, i)) +- i = i + 1; ++ # ++ test.write(" %s = gen_%s(n_%s, %d);\n" % (nam, type, nam, i)) ++ i = i + 1; + + # add checks to avoid out-of-bounds array access + i = 0; +@@ -797,7 +797,7 @@ test_%s(void) { + # assume that "size", "len", and "start" parameters apply to either + # the nearest preceding or following char pointer + if type == "int" and (nam == "size" or nam == "len" or nam == "start"): +- for j in range(i - 1, -1, -1) + range(i + 1, len(t_args)): ++ for j in (*range(i - 1, -1, -1), *range(i + 1, len(t_args))): + (bnam, btype) = t_args[j][:2] + if btype == "const_char_ptr" or btype == "const_xmlChar_ptr": + test.write( +@@ -806,42 +806,42 @@ test_%s(void) { + " continue;\n" + % (bnam, nam, bnam)) + break +- i = i + 1; ++ i = i + 1; + + # do the call, and clanup the result +- if extra_pre_call.has_key(name): +- test.write(" %s\n"% (extra_pre_call[name])) ++ if name in extra_pre_call: ++ test.write(" %s\n"% (extra_pre_call[name])) + if t_ret != None: +- test.write("\n ret_val = %s(" % (name)) +- need = 0 +- for arg in t_args: +- (nam, type, rtype, crtype, info) = arg +- if need: +- test.write(", ") +- else: +- need = 1 +- if rtype != crtype: +- test.write("(%s)" % rtype) +- test.write("%s" % nam); +- test.write(");\n") +- if extra_post_call.has_key(name): +- test.write(" %s\n"% (extra_post_call[name])) +- test.write(" desret_%s(ret_val);\n" % t_ret[0]) ++ test.write("\n ret_val = %s(" % (name)) ++ need = 0 ++ for arg in t_args: ++ (nam, type, rtype, crtype, info) = arg ++ if need: ++ test.write(", ") ++ else: ++ need = 1 ++ if rtype != crtype: ++ test.write("(%s)" % rtype) ++ test.write("%s" % nam); ++ test.write(");\n") ++ if name in extra_post_call: ++ test.write(" %s\n"% (extra_post_call[name])) ++ test.write(" desret_%s(ret_val);\n" % t_ret[0]) + else: +- test.write("\n %s(" % (name)); +- need = 0; +- for arg in t_args: +- (nam, type, rtype, crtype, info) = arg; +- if need: +- test.write(", ") +- else: +- need = 1 +- if rtype != crtype: +- test.write("(%s)" % rtype) +- test.write("%s" % nam) +- test.write(");\n") +- if extra_post_call.has_key(name): +- test.write(" %s\n"% (extra_post_call[name])) ++ test.write("\n %s(" % (name)); ++ need = 0; ++ for arg in t_args: ++ (nam, type, rtype, crtype, info) = arg; ++ if need: ++ test.write(", ") ++ else: ++ need = 1 ++ if rtype != crtype: ++ test.write("(%s)" % rtype) ++ test.write("%s" % nam) ++ test.write(");\n") ++ if name in extra_post_call: ++ test.write(" %s\n"% (extra_post_call[name])) + + test.write(" call_tests++;\n"); + +@@ -849,32 +849,32 @@ test_%s(void) { + i = 0; + for arg in t_args: + (nam, type, rtype, crtype, info) = arg; +- # This is a hack to prevent generating a destructor for the +- # 'input' argument in xmlTextReaderSetup. There should be +- # a better, more generic way to do this! +- if string.find(info, 'destroy') == -1: +- test.write(" des_%s(n_%s, " % (type, nam)) +- if rtype != crtype: +- test.write("(%s)" % rtype) +- test.write("%s, %d);\n" % (nam, i)) +- i = i + 1; ++ # This is a hack to prevent generating a destructor for the ++ # 'input' argument in xmlTextReaderSetup. There should be ++ # a better, more generic way to do this! ++ if info.find('destroy') == -1: ++ test.write(" des_%s(n_%s, " % (type, nam)) ++ if rtype != crtype: ++ test.write("(%s)" % rtype) ++ test.write("%s, %d);\n" % (nam, i)) ++ i = i + 1; + + test.write(" xmlResetLastError();\n"); + # Check the memory usage + if no_mem == 0: +- test.write(""" if (mem_base != xmlMemBlocks()) { ++ test.write(""" if (mem_base != xmlMemBlocks()) { + printf("Leak of %%d blocks found in %s", +- xmlMemBlocks() - mem_base); +- test_ret++; ++\t xmlMemBlocks() - mem_base); ++\t test_ret++; + """ % (name)); +- for arg in t_args: +- (nam, type, rtype, crtype, info) = arg; +- test.write(""" printf(" %%d", n_%s);\n""" % (nam)) +- test.write(""" printf("\\n");\n""") +- test.write(" }\n") ++ for arg in t_args: ++ (nam, type, rtype, crtype, info) = arg; ++ test.write(""" printf(" %%d", n_%s);\n""" % (nam)) ++ test.write(""" printf("\\n");\n""") ++ test.write(" }\n") + + for arg in t_args: +- test.write(" }\n") ++ test.write(" }\n") + + test.write(" function_tests++;\n") + # +@@ -882,7 +882,7 @@ test_%s(void) { + # + while nb_cond > 0: + test.write("#endif\n") +- nb_cond = nb_cond -1 ++ nb_cond = nb_cond -1 + if define == 1: + test.write("#endif\n") + +@@ -900,10 +900,10 @@ test_%s(void) { + for module in modules: + # gather all the functions exported by that module + try: +- functions = ctxt.xpathEval("/api/symbols/function[@file='%s']" % (module)) ++ functions = ctxt.xpathEval("/api/symbols/function[@file='%s']" % (module)) + except: +- print "Failed to gather functions from module %s" % (module) +- continue; ++ print("Failed to gather functions from module %s" % (module)) ++ continue; + + # iterate over all functions in the module generating the test + i = 0 +@@ -923,14 +923,14 @@ test_%s(void) { + # iterate over all functions in the module generating the call + for function in functions: + name = function.xpathEval('string(@name)') +- if is_skipped_function(name): +- continue +- test.write(" test_ret += test_%s();\n" % (name)) ++ if is_skipped_function(name): ++ continue ++ test.write(" test_ret += test_%s();\n" % (name)) + + # footer + test.write(""" + if (test_ret != 0) +- printf("Module %s: %%d errors\\n", test_ret); ++\tprintf("Module %s: %%d errors\\n", test_ret); + return(test_ret); + } + """ % (module)) +@@ -948,7 +948,7 @@ test.write(""" return(0); + } + """); + +-print "Generated test for %d modules and %d functions" %(len(modules), nb_tests) ++print("Generated test for %d modules and %d functions" %(len(modules), nb_tests)) + + compare_and_save() + +@@ -960,11 +960,8 @@ for missing in missing_types.keys(): + n = len(missing_types[missing]) + missing_list.append((n, missing)) + +-def compare_missing(a, b): +- return b[0] - a[0] +- +-missing_list.sort(compare_missing) +-print "Missing support for %d functions and %d types see missing.lst" % (missing_functions_nr, len(missing_list)) ++missing_list.sort(key=lambda a: a[0]) ++print("Missing support for %d functions and %d types see missing.lst" % (missing_functions_nr, len(missing_list))) + lst = open("missing.lst", "w") + lst.write("Missing support for %d types" % (len(missing_list))) + lst.write("\n") +@@ -974,9 +971,9 @@ for miss in missing_list: + for n in missing_types[miss[1]]: + i = i + 1 + if i > 5: +- lst.write(" ...") +- break +- lst.write(" %s" % (n)) ++ lst.write(" ...") ++ break ++ lst.write(" %s" % (n)) + lst.write("\n") + lst.write("\n") + lst.write("\n") diff --git a/meta/recipes-core/libxml/libxml2/CVE-2016-3709.patch b/meta/recipes-core/libxml/libxml2/CVE-2016-3709.patch new file mode 100644 index 0000000000..5301d05323 --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2016-3709.patch @@ -0,0 +1,89 @@ +From c1ba6f54d32b707ca6d91cb3257ce9de82876b6f Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Sat, 15 Aug 2020 18:32:29 +0200 +Subject: [PATCH] Revert "Do not URI escape in server side includes" + +This reverts commit 960f0e275616cadc29671a218d7fb9b69eb35588. + +This commit introduced + +- an infinite loop, found by OSS-Fuzz, which could be easily fixed. +- an algorithm with quadratic runtime +- a security issue, see + https://bugzilla.gnome.org/show_bug.cgi?id=769760 + +A better approach is to add an option not to escape URLs at all +which libxml2 should have possibly done in the first place. + +CVE: CVE-2016-3709 +Upstream-Status: Backport [https://github.com/GNOME/libxml2/commit/c1ba6f54d32b707ca6d91cb3257ce9de82876b6f] +Signed-off-by: Pawan Badganchi <Pawan.Badganchi@kpit.com> +--- + HTMLtree.c | 49 +++++++++++-------------------------------------- + 1 file changed, 11 insertions(+), 38 deletions(-) + +diff --git a/HTMLtree.c b/HTMLtree.c +index 8d236bb35..cdb7f86a6 100644 +--- a/HTMLtree.c ++++ b/HTMLtree.c +@@ -706,49 +706,22 @@ htmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur, + (!xmlStrcasecmp(cur->name, BAD_CAST "src")) || + ((!xmlStrcasecmp(cur->name, BAD_CAST "name")) && + (!xmlStrcasecmp(cur->parent->name, BAD_CAST "a"))))) { ++ xmlChar *escaped; + xmlChar *tmp = value; +- /* xmlURIEscapeStr() escapes '"' so it can be safely used. */ +- xmlBufCCat(buf->buffer, "\""); + + while (IS_BLANK_CH(*tmp)) tmp++; + +- /* URI Escape everything, except server side includes. */ +- for ( ; ; ) { +- xmlChar *escaped; +- xmlChar endChar; +- xmlChar *end = NULL; +- xmlChar *start = (xmlChar *)xmlStrstr(tmp, BAD_CAST "<!--"); +- if (start != NULL) { +- end = (xmlChar *)xmlStrstr(tmp, BAD_CAST "-->"); +- if (end != NULL) { +- *start = '\0'; +- } +- } +- +- /* Escape the whole string, or until start (set to '\0'). */ +- escaped = xmlURIEscapeStr(tmp, BAD_CAST"@/:=?;#%&,+"); +- if (escaped != NULL) { +- xmlBufCat(buf->buffer, escaped); +- xmlFree(escaped); +- } else { +- xmlBufCat(buf->buffer, tmp); +- } +- +- if (end == NULL) { /* Everything has been written. */ +- break; +- } +- +- /* Do not escape anything within server side includes. */ +- *start = '<'; /* Restore the first character of "<!--". */ +- end += 3; /* strlen("-->") */ +- endChar = *end; +- *end = '\0'; +- xmlBufCat(buf->buffer, start); +- *end = endChar; +- tmp = end; ++ /* ++ * the < and > have already been escaped at the entity level ++ * And doing so here breaks server side includes ++ */ ++ escaped = xmlURIEscapeStr(tmp, BAD_CAST"@/:=?;#%&,+<>"); ++ if (escaped != NULL) { ++ xmlBufWriteQuotedString(buf->buffer, escaped); ++ xmlFree(escaped); ++ } else { ++ xmlBufWriteQuotedString(buf->buffer, value); + } +- +- xmlBufCCat(buf->buffer, "\""); + } else { + xmlBufWriteQuotedString(buf->buffer, value); + } diff --git a/meta/recipes-core/libxml/libxml2/CVE-2021-3516.patch b/meta/recipes-core/libxml/libxml2/CVE-2021-3516.patch new file mode 100644 index 0000000000..200f42091e --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2021-3516.patch @@ -0,0 +1,35 @@ +From 1358d157d0bd83be1dfe356a69213df9fac0b539 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Wed, 21 Apr 2021 13:23:27 +0200 +Subject: [PATCH] Fix use-after-free with `xmllint --html --push` + +Call htmlCtxtUseOptions to make sure that names aren't stored in +dictionaries. + +Note that this issue only affects xmllint using the HTML push parser. + +Fixes #230. + +Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/1358d157d0bd83be1dfe356a69213df9fac0b539] +CVE: CVE-2021-3516 +Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> +--- + xmllint.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xmllint.c b/xmllint.c +index 6ca1bf54d..dbef273a8 100644 +--- a/xmllint.c ++++ b/xmllint.c +@@ -2213,7 +2213,7 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) { + if (res > 0) { + ctxt = htmlCreatePushParserCtxt(NULL, NULL, + chars, res, filename, XML_CHAR_ENCODING_NONE); +- xmlCtxtUseOptions(ctxt, options); ++ htmlCtxtUseOptions(ctxt, options); + while ((res = fread(chars, 1, pushsize, f)) > 0) { + htmlParseChunk(ctxt, chars, res, 0); + } +-- +GitLab + diff --git a/meta/recipes-core/libxml/libxml2/CVE-2021-3518.patch b/meta/recipes-core/libxml/libxml2/CVE-2021-3518.patch new file mode 100644 index 0000000000..40d3debea1 --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2021-3518.patch @@ -0,0 +1,112 @@ +From ac82a514e16eb81b4506e2cba1a1ee45b9f025b5 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Wed, 10 Jun 2020 16:34:52 +0200 +Subject: [PATCH 1/2] Don't recurse into xi:include children in + xmlXIncludeDoProcess + +Otherwise, nested xi:include nodes might result in a use-after-free +if XML_PARSE_NOXINCNODE is specified. + +Found with libFuzzer and ASan. + +Upstream-Status: Backport [from fedora: https://bugzilla.redhat.com/show_bug.cgi?id=1954243] + +The upstream patch 752e5f71d7cea2ca5a7e7c0b8f72ed04ce654be4 has been modified, +as to avoid unnecessary modifications to fallback files. + +CVE: CVE-2021-3518 +Signed-off-by: Jasper Orschulko <Jasper.Orschulko@iris-sensing.com> +--- + xinclude.c | 24 ++++++++++-------------- + 1 file changed, 10 insertions(+), 14 deletions(-) + +diff --git a/xinclude.c b/xinclude.c +index ba850fa5..f260c1a7 100644 +--- a/xinclude.c ++++ b/xinclude.c +@@ -2392,21 +2392,19 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) { + * First phase: lookup the elements in the document + */ + cur = tree; +- if (xmlXIncludeTestNode(ctxt, cur) == 1) +- xmlXIncludePreProcessNode(ctxt, cur); + while ((cur != NULL) && (cur != tree->parent)) { + /* TODO: need to work on entities -> stack */ +- if ((cur->children != NULL) && +- (cur->children->type != XML_ENTITY_DECL) && +- (cur->children->type != XML_XINCLUDE_START) && +- (cur->children->type != XML_XINCLUDE_END)) { +- cur = cur->children; +- if (xmlXIncludeTestNode(ctxt, cur)) +- xmlXIncludePreProcessNode(ctxt, cur); +- } else if (cur->next != NULL) { ++ if (xmlXIncludeTestNode(ctxt, cur) == 1) { ++ xmlXIncludePreProcessNode(ctxt, cur); ++ } else if ((cur->children != NULL) && ++ (cur->children->type != XML_ENTITY_DECL) && ++ (cur->children->type != XML_XINCLUDE_START) && ++ (cur->children->type != XML_XINCLUDE_END)) { ++ cur = cur->children; ++ continue; ++ } ++ if (cur->next != NULL) { + cur = cur->next; +- if (xmlXIncludeTestNode(ctxt, cur)) +- xmlXIncludePreProcessNode(ctxt, cur); + } else { + if (cur == tree) + break; +@@ -2416,8 +2414,6 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) { + break; /* do */ + if (cur->next != NULL) { + cur = cur->next; +- if (xmlXIncludeTestNode(ctxt, cur)) +- xmlXIncludePreProcessNode(ctxt, cur); + break; /* do */ + } + } while (cur != NULL); +-- +2.32.0 + + +From 3ad5ac1e39e3cd42f838c1cd27ffd4e9b79e6121 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Thu, 22 Apr 2021 19:26:28 +0200 +Subject: [PATCH 2/2] Fix user-after-free with `xmllint --xinclude --dropdtd` + +The --dropdtd option can leave dangling pointers in entity reference +nodes. Make sure to skip these nodes when processing XIncludes. + +This also avoids scanning entity declarations and even modifying +them inadvertently during XInclude processing. + +Move from a block list to an allow list approach to avoid descending +into other node types that can't contain elements. + +Fixes #237. +Upstream-Status: Backport +CVE: CVE-2021-3518 +Signed-off-by: Jasper Orschulko <Jasper.Orschulko@iris-sensing.com> +--- + xinclude.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/xinclude.c b/xinclude.c +index f260c1a7..d7648529 100644 +--- a/xinclude.c ++++ b/xinclude.c +@@ -2397,9 +2397,8 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) { + if (xmlXIncludeTestNode(ctxt, cur) == 1) { + xmlXIncludePreProcessNode(ctxt, cur); + } else if ((cur->children != NULL) && +- (cur->children->type != XML_ENTITY_DECL) && +- (cur->children->type != XML_XINCLUDE_START) && +- (cur->children->type != XML_XINCLUDE_END)) { ++ ((cur->type == XML_DOCUMENT_NODE) || ++ (cur->type == XML_ELEMENT_NODE))) { + cur = cur->children; + continue; + } +-- +2.32.0 + diff --git a/meta/recipes-core/libxml/libxml2/CVE-2021-3541.patch b/meta/recipes-core/libxml/libxml2/CVE-2021-3541.patch new file mode 100644 index 0000000000..1f392b4cd7 --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2021-3541.patch @@ -0,0 +1,73 @@ +From 8598060bacada41a0eb09d95c97744ff4e428f8e Mon Sep 17 00:00:00 2001 +From: Daniel Veillard <veillard@redhat.com> +Date: Thu, 13 May 2021 14:55:12 +0200 +Subject: [PATCH] Patch for security issue CVE-2021-3541 + +This is relapted to parameter entities expansion and following +the line of the billion laugh attack. Somehow in that path the +counting of parameters was missed and the normal algorithm based +on entities "density" was useless. + +Upstream-Status: Backport +[https://gitlab.gnome.org/GNOME/libxml2/-/commit/8598060bacada41a0eb09d95c97744ff4e428f8e] +CVE: CVE-2021-3541 +Signed-off-by: Steve Sakoman <steve@sakoman.com> + +--- + parser.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/parser.c b/parser.c +index f5e5e169..c9312fa4 100644 +--- a/parser.c ++++ b/parser.c +@@ -140,6 +140,7 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size, + xmlEntityPtr ent, size_t replacement) + { + size_t consumed = 0; ++ int i; + + if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE)) + return (0); +@@ -177,6 +178,28 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size, + rep = NULL; + } + } ++ ++ /* ++ * Prevent entity exponential check, not just replacement while ++ * parsing the DTD ++ * The check is potentially costly so do that only once in a thousand ++ */ ++ if ((ctxt->instate == XML_PARSER_DTD) && (ctxt->nbentities > 10000) && ++ (ctxt->nbentities % 1024 == 0)) { ++ for (i = 0;i < ctxt->inputNr;i++) { ++ consumed += ctxt->inputTab[i]->consumed + ++ (ctxt->inputTab[i]->cur - ctxt->inputTab[i]->base); ++ } ++ if (ctxt->nbentities > consumed * XML_PARSER_NON_LINEAR) { ++ xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL); ++ ctxt->instate = XML_PARSER_EOF; ++ return (1); ++ } ++ consumed = 0; ++ } ++ ++ ++ + if (replacement != 0) { + if (replacement < XML_MAX_TEXT_LENGTH) + return(0); +@@ -7963,6 +7986,9 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt) + xmlChar start[4]; + xmlCharEncoding enc; + ++ if (xmlParserEntityCheck(ctxt, 0, entity, 0)) ++ return; ++ + if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) && + ((ctxt->options & XML_PARSE_NOENT) == 0) && + ((ctxt->options & XML_PARSE_DTDVALID) == 0) && +-- +GitLab + diff --git a/meta/recipes-core/libxml/libxml2/CVE-2022-23308-fix-regression.patch b/meta/recipes-core/libxml/libxml2/CVE-2022-23308-fix-regression.patch new file mode 100644 index 0000000000..7fc243eec1 --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2022-23308-fix-regression.patch @@ -0,0 +1,98 @@ +From 646fe48d1c8a74310c409ddf81fe7df6700052af Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Tue, 22 Feb 2022 11:51:08 +0100 +Subject: [PATCH] Fix --without-valid build + +Regressed in commit 652dd12a. +--- + valid.c | 58 ++++++++++++++++++++++++++++----------------------------- + 1 file changed, 29 insertions(+), 29 deletions(-) +--- + +From https://github.com/GNOME/libxml2.git + commit 646fe48d1c8a74310c409ddf81fe7df6700052af + +CVE: CVE-2022-23308 +Upstream-Status: Backport + +Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org> + +diff --git a/valid.c b/valid.c +index 8e596f1d..9684683a 100644 +--- a/valid.c ++++ b/valid.c +@@ -479,35 +479,6 @@ nodeVPop(xmlValidCtxtPtr ctxt) + return (ret); + } + +-/** +- * xmlValidNormalizeString: +- * @str: a string +- * +- * Normalize a string in-place. +- */ +-static void +-xmlValidNormalizeString(xmlChar *str) { +- xmlChar *dst; +- const xmlChar *src; +- +- if (str == NULL) +- return; +- src = str; +- dst = str; +- +- while (*src == 0x20) src++; +- while (*src != 0) { +- if (*src == 0x20) { +- while (*src == 0x20) src++; +- if (*src != 0) +- *dst++ = 0x20; +- } else { +- *dst++ = *src++; +- } +- } +- *dst = 0; +-} +- + #ifdef DEBUG_VALID_ALGO + static void + xmlValidPrintNode(xmlNodePtr cur) { +@@ -2636,6 +2607,35 @@ xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) { + (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \ + xmlFree((char *)(str)); + ++/** ++ * xmlValidNormalizeString: ++ * @str: a string ++ * ++ * Normalize a string in-place. ++ */ ++static void ++xmlValidNormalizeString(xmlChar *str) { ++ xmlChar *dst; ++ const xmlChar *src; ++ ++ if (str == NULL) ++ return; ++ src = str; ++ dst = str; ++ ++ while (*src == 0x20) src++; ++ while (*src != 0) { ++ if (*src == 0x20) { ++ while (*src == 0x20) src++; ++ if (*src != 0) ++ *dst++ = 0x20; ++ } else { ++ *dst++ = *src++; ++ } ++ } ++ *dst = 0; ++} ++ + static int + xmlIsStreaming(xmlValidCtxtPtr ctxt) { + xmlParserCtxtPtr pctxt; +-- +2.35.1 + diff --git a/meta/recipes-core/libxml/libxml2/CVE-2022-23308.patch b/meta/recipes-core/libxml/libxml2/CVE-2022-23308.patch new file mode 100644 index 0000000000..bf5604e81a --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2022-23308.patch @@ -0,0 +1,204 @@ +From 8b66850de350f0fcd786ae776a65ba15a5999e50 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Tue, 8 Feb 2022 03:29:24 +0100 +Subject: [PATCH] Use-after-free of ID and IDREF attributes + +If a document is parsed with XML_PARSE_DTDVALID and without +XML_PARSE_NOENT, the value of ID attributes has to be normalized after +potentially expanding entities in xmlRemoveID. Otherwise, later calls +to xmlGetID can return a pointer to previously freed memory. + +ID attributes which are empty or contain only whitespace after +entity expansion are affected in a similar way. This is fixed by +not storing such attributes in the ID table. + +The test to detect streaming mode when validating against a DTD was +broken. In connection with the defects above, this could result in a +use-after-free when using the xmlReader interface with validation. +Fix detection of streaming mode to avoid similar issues. (This changes +the expected result of a test case. But as far as I can tell, using the +XML reader with XIncludes referencing the root document never worked +properly, anyway.) + +All of these issues can result in denial of service. Using xmlReader +with validation could result in disclosure of memory via the error +channel, typically stderr. The security impact of xmlGetID returning +a pointer to freed memory depends on the application. The typical use +case of calling xmlGetID on an unmodified document is not affected. + +Upstream-Status: Backport +[https://gitlab.gnome.org/GNOME/libxml2/-/commit/652dd12a858989b14eed4e84e453059cd3ba340e] + +The upstream patch 652dd12a858989b14eed4e84e453059cd3ba340e has been modified +to skip the patch to the testsuite result (result/XInclude/ns1.xml.rdr), as +this particular test does not exist in v2.9.10 (it was added later). + +CVE: CVE-2022-23308 +Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org> + +--- + valid.c | 88 +++++++++++++++++++++++++++++++++++---------------------- + 1 file changed, 55 insertions(+), 33 deletions(-) + +diff --git a/valid.c b/valid.c +index 07963e7..ee75311 100644 +--- a/valid.c ++++ b/valid.c +@@ -479,6 +479,35 @@ nodeVPop(xmlValidCtxtPtr ctxt) + return (ret); + } + ++/** ++ * xmlValidNormalizeString: ++ * @str: a string ++ * ++ * Normalize a string in-place. ++ */ ++static void ++xmlValidNormalizeString(xmlChar *str) { ++ xmlChar *dst; ++ const xmlChar *src; ++ ++ if (str == NULL) ++ return; ++ src = str; ++ dst = str; ++ ++ while (*src == 0x20) src++; ++ while (*src != 0) { ++ if (*src == 0x20) { ++ while (*src == 0x20) src++; ++ if (*src != 0) ++ *dst++ = 0x20; ++ } else { ++ *dst++ = *src++; ++ } ++ } ++ *dst = 0; ++} ++ + #ifdef DEBUG_VALID_ALGO + static void + xmlValidPrintNode(xmlNodePtr cur) { +@@ -2607,6 +2636,24 @@ xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) { + (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \ + xmlFree((char *)(str)); + ++static int ++xmlIsStreaming(xmlValidCtxtPtr ctxt) { ++ xmlParserCtxtPtr pctxt; ++ ++ if (ctxt == NULL) ++ return(0); ++ /* ++ * These magic values are also abused to detect whether we're validating ++ * while parsing a document. In this case, userData points to the parser ++ * context. ++ */ ++ if ((ctxt->finishDtd != XML_CTXT_FINISH_DTD_0) && ++ (ctxt->finishDtd != XML_CTXT_FINISH_DTD_1)) ++ return(0); ++ pctxt = ctxt->userData; ++ return(pctxt->parseMode == XML_PARSE_READER); ++} ++ + /** + * xmlFreeID: + * @not: A id +@@ -2650,7 +2697,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, + if (doc == NULL) { + return(NULL); + } +- if (value == NULL) { ++ if ((value == NULL) || (value[0] == 0)) { + return(NULL); + } + if (attr == NULL) { +@@ -2681,7 +2728,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, + */ + ret->value = xmlStrdup(value); + ret->doc = doc; +- if ((ctxt != NULL) && (ctxt->vstateNr != 0)) { ++ if (xmlIsStreaming(ctxt)) { + /* + * Operating in streaming mode, attr is gonna disappear + */ +@@ -2820,6 +2867,7 @@ xmlRemoveID(xmlDocPtr doc, xmlAttrPtr attr) { + ID = xmlNodeListGetString(doc, attr->children, 1); + if (ID == NULL) + return(-1); ++ xmlValidNormalizeString(ID); + + id = xmlHashLookup(table, ID); + if (id == NULL || id->attr != attr) { +@@ -3009,7 +3057,7 @@ xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, + * fill the structure. + */ + ret->value = xmlStrdup(value); +- if ((ctxt != NULL) && (ctxt->vstateNr != 0)) { ++ if (xmlIsStreaming(ctxt)) { + /* + * Operating in streaming mode, attr is gonna disappear + */ +@@ -4028,8 +4076,7 @@ xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt, xmlDocPtr doc, + xmlChar * + xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc, + xmlNodePtr elem, const xmlChar *name, const xmlChar *value) { +- xmlChar *ret, *dst; +- const xmlChar *src; ++ xmlChar *ret; + xmlAttributePtr attrDecl = NULL; + int extsubset = 0; + +@@ -4070,19 +4117,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc, + ret = xmlStrdup(value); + if (ret == NULL) + return(NULL); +- src = value; +- dst = ret; +- while (*src == 0x20) src++; +- while (*src != 0) { +- if (*src == 0x20) { +- while (*src == 0x20) src++; +- if (*src != 0) +- *dst++ = 0x20; +- } else { +- *dst++ = *src++; +- } +- } +- *dst = 0; ++ xmlValidNormalizeString(ret); + if ((doc->standalone) && (extsubset == 1) && (!xmlStrEqual(value, ret))) { + xmlErrValidNode(ctxt, elem, XML_DTD_NOT_STANDALONE, + "standalone: %s on %s value had to be normalized based on external subset declaration\n", +@@ -4114,8 +4149,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc, + xmlChar * + xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem, + const xmlChar *name, const xmlChar *value) { +- xmlChar *ret, *dst; +- const xmlChar *src; ++ xmlChar *ret; + xmlAttributePtr attrDecl = NULL; + + if (doc == NULL) return(NULL); +@@ -4145,19 +4179,7 @@ xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem, + ret = xmlStrdup(value); + if (ret == NULL) + return(NULL); +- src = value; +- dst = ret; +- while (*src == 0x20) src++; +- while (*src != 0) { +- if (*src == 0x20) { +- while (*src == 0x20) src++; +- if (*src != 0) +- *dst++ = 0x20; +- } else { +- *dst++ = *src++; +- } +- } +- *dst = 0; ++ xmlValidNormalizeString(ret); + return(ret); + } + diff --git a/meta/recipes-core/libxml/libxml2/CVE-2022-29824-dependent.patch b/meta/recipes-core/libxml/libxml2/CVE-2022-29824-dependent.patch new file mode 100644 index 0000000000..63d613cc21 --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2022-29824-dependent.patch @@ -0,0 +1,53 @@ +From b07251215ef48c70c6e56f7351406c47cfca4d5b Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Fri, 10 Jan 2020 15:55:07 +0100 +Subject: [PATCH] Fix integer overflow in xmlBufferResize + +Found by OSS-Fuzz. + +CVE: CVE-2022-29824 + +Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/b07251215ef48c70c6e56f7351406c47cfca4d5b] + +Signed-off-by: Riyaz Ahmed Khan <Riyaz.Khan@kpit.com> + +--- + tree.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/tree.c b/tree.c +index 0d7fc98c..f43f6de1 100644 +--- a/tree.c ++++ b/tree.c +@@ -7424,12 +7424,17 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size) + if (size < buf->size) + return 1; + ++ if (size > UINT_MAX - 10) { ++ xmlTreeErrMemory("growing buffer"); ++ return 0; ++ } ++ + /* figure out new size */ + switch (buf->alloc){ + case XML_BUFFER_ALLOC_IO: + case XML_BUFFER_ALLOC_DOUBLEIT: + /*take care of empty case*/ +- newSize = (buf->size ? buf->size*2 : size + 10); ++ newSize = (buf->size ? buf->size : size + 10); + while (size > newSize) { + if (newSize > UINT_MAX / 2) { + xmlTreeErrMemory("growing buffer"); +@@ -7445,7 +7450,7 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size) + if (buf->use < BASE_BUFFER_SIZE) + newSize = size; + else { +- newSize = buf->size * 2; ++ newSize = buf->size; + while (size > newSize) { + if (newSize > UINT_MAX / 2) { + xmlTreeErrMemory("growing buffer"); +-- +GitLab + + diff --git a/meta/recipes-core/libxml/libxml2/CVE-2022-29824.patch b/meta/recipes-core/libxml/libxml2/CVE-2022-29824.patch new file mode 100644 index 0000000000..ad7b87dbc6 --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2022-29824.patch @@ -0,0 +1,348 @@ +From 2554a2408e09f13652049e5ffb0d26196b02ebab Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Tue, 8 Mar 2022 20:10:02 +0100 +Subject: [PATCH] [CVE-2022-29824] Fix integer overflows in xmlBuf and + xmlBuffer + +In several places, the code handling string buffers didn't check for +integer overflow or used wrong types for buffer sizes. This could +result in out-of-bounds writes or other memory errors when working on +large, multi-gigabyte buffers. + +Thanks to Felix Wilhelm for the report. + +CVE: CVE-2022-29824 + +Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/2554a2408e09f13652049e5ffb0d26196b02ebab] + +Signed-off-by: Riyaz Ahmed Khan <Riyaz.Khan@kpit.com> + +--- + buf.c | 86 +++++++++++++++++++++++----------------------------------- + tree.c | 72 ++++++++++++++++++------------------------------ + 2 files changed, 61 insertions(+), 97 deletions(-) + +diff --git a/buf.c b/buf.c +index 24368d37..40a5ee06 100644 +--- a/buf.c ++++ b/buf.c +@@ -30,6 +30,10 @@ + #include <libxml/parserInternals.h> /* for XML_MAX_TEXT_LENGTH */ + #include "buf.h" + ++#ifndef SIZE_MAX ++#define SIZE_MAX ((size_t) -1) ++#endif ++ + #define WITH_BUFFER_COMPAT + + /** +@@ -156,6 +160,8 @@ xmlBufPtr + xmlBufCreateSize(size_t size) { + xmlBufPtr ret; + ++ if (size == SIZE_MAX) ++ return(NULL); + ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf)); + if (ret == NULL) { + xmlBufMemoryError(NULL, "creating buffer"); +@@ -166,8 +172,8 @@ xmlBufCreateSize(size_t size) { + ret->error = 0; + ret->buffer = NULL; + ret->alloc = xmlBufferAllocScheme; +- ret->size = (size ? size+2 : 0); /* +1 for ending null */ +- ret->compat_size = (int) ret->size; ++ ret->size = (size ? size + 1 : 0); /* +1 for ending null */ ++ ret->compat_size = (ret->size > INT_MAX ? INT_MAX : ret->size); + if (ret->size){ + ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar)); + if (ret->content == NULL) { +@@ -442,23 +448,17 @@ xmlBufGrowInternal(xmlBufPtr buf, size_t len) { + CHECK_COMPAT(buf) + + if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0); +- if (buf->use + len < buf->size) ++ if (len < buf->size - buf->use) + return(buf->size - buf->use); ++ if (len > SIZE_MAX - buf->use) ++ return(0); + +- /* +- * Windows has a BIG problem on realloc timing, so we try to double +- * the buffer size (if that's enough) (bug 146697) +- * Apparently BSD too, and it's probably best for linux too +- * On an embedded system this may be something to change +- */ +-#if 1 +- if (buf->size > (size_t) len) +- size = buf->size * 2; +- else +- size = buf->use + len + 100; +-#else +- size = buf->use + len + 100; +-#endif ++ if (buf->size > (size_t) len) { ++ size = buf->size > SIZE_MAX / 2 ? SIZE_MAX : buf->size * 2; ++ } else { ++ size = buf->use + len; ++ size = size > SIZE_MAX - 100 ? SIZE_MAX : size + 100; ++ } + + if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) { + /* +@@ -744,7 +744,7 @@ xmlBufIsEmpty(const xmlBufPtr buf) + int + xmlBufResize(xmlBufPtr buf, size_t size) + { +- unsigned int newSize; ++ size_t newSize; + xmlChar* rebuf = NULL; + size_t start_buf; + +@@ -772,9 +772,13 @@ xmlBufResize(xmlBufPtr buf, size_t size) + case XML_BUFFER_ALLOC_IO: + case XML_BUFFER_ALLOC_DOUBLEIT: + /*take care of empty case*/ +- newSize = (buf->size ? buf->size*2 : size + 10); ++ if (buf->size == 0) { ++ newSize = (size > SIZE_MAX - 10 ? SIZE_MAX : size + 10); ++ } else { ++ newSize = buf->size; ++ } + while (size > newSize) { +- if (newSize > UINT_MAX / 2) { ++ if (newSize > SIZE_MAX / 2) { + xmlBufMemoryError(buf, "growing buffer"); + return 0; + } +@@ -782,15 +786,15 @@ xmlBufResize(xmlBufPtr buf, size_t size) + } + break; + case XML_BUFFER_ALLOC_EXACT: +- newSize = size+10; ++ newSize = (size > SIZE_MAX - 10 ? SIZE_MAX : size + 10); + break; + case XML_BUFFER_ALLOC_HYBRID: + if (buf->use < BASE_BUFFER_SIZE) + newSize = size; + else { +- newSize = buf->size * 2; ++ newSize = buf->size; + while (size > newSize) { +- if (newSize > UINT_MAX / 2) { ++ if (newSize > SIZE_MAX / 2) { + xmlBufMemoryError(buf, "growing buffer"); + return 0; + } +@@ -800,7 +804,7 @@ xmlBufResize(xmlBufPtr buf, size_t size) + break; + + default: +- newSize = size+10; ++ newSize = (size > SIZE_MAX - 10 ? SIZE_MAX : size + 10); + break; + } + +@@ -866,7 +870,7 @@ xmlBufResize(xmlBufPtr buf, size_t size) + */ + int + xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) { +- unsigned int needSize; ++ size_t needSize; + + if ((str == NULL) || (buf == NULL) || (buf->error)) + return -1; +@@ -888,8 +892,10 @@ xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) { + if (len < 0) return -1; + if (len == 0) return 0; + +- needSize = buf->use + len + 2; +- if (needSize > buf->size){ ++ if ((size_t) len >= buf->size - buf->use) { ++ if ((size_t) len >= SIZE_MAX - buf->use) ++ return(-1); ++ needSize = buf->use + len + 1; + if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) { + /* + * Used to provide parsing limits +@@ -1025,31 +1031,7 @@ xmlBufCat(xmlBufPtr buf, const xmlChar *str) { + */ + int + xmlBufCCat(xmlBufPtr buf, const char *str) { +- const char *cur; +- +- if ((buf == NULL) || (buf->error)) +- return(-1); +- CHECK_COMPAT(buf) +- if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1; +- if (str == NULL) { +-#ifdef DEBUG_BUFFER +- xmlGenericError(xmlGenericErrorContext, +- "xmlBufCCat: str == NULL\n"); +-#endif +- return -1; +- } +- for (cur = str;*cur != 0;cur++) { +- if (buf->use + 10 >= buf->size) { +- if (!xmlBufResize(buf, buf->use+10)){ +- xmlBufMemoryError(buf, "growing buffer"); +- return XML_ERR_NO_MEMORY; +- } +- } +- buf->content[buf->use++] = *cur; +- } +- buf->content[buf->use] = 0; +- UPDATE_COMPAT(buf) +- return 0; ++ return xmlBufCat(buf, (const xmlChar *) str); + } + + /** +diff --git a/tree.c b/tree.c +index 9d94aa42..86afb7d6 100644 +--- a/tree.c ++++ b/tree.c +@@ -7104,6 +7104,8 @@ xmlBufferPtr + xmlBufferCreateSize(size_t size) { + xmlBufferPtr ret; + ++ if (size >= UINT_MAX) ++ return(NULL); + ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer)); + if (ret == NULL) { + xmlTreeErrMemory("creating buffer"); +@@ -7111,7 +7113,7 @@ xmlBufferCreateSize(size_t size) { + } + ret->use = 0; + ret->alloc = xmlBufferAllocScheme; +- ret->size = (size ? size+2 : 0); /* +1 for ending null */ ++ ret->size = (size ? size + 1 : 0); /* +1 for ending null */ + if (ret->size){ + ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar)); + if (ret->content == NULL) { +@@ -7171,6 +7173,8 @@ xmlBufferCreateStatic(void *mem, size_t size) { + + if ((mem == NULL) || (size == 0)) + return(NULL); ++ if (size > UINT_MAX) ++ return(NULL); + + ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer)); + if (ret == NULL) { +@@ -7318,28 +7322,23 @@ xmlBufferShrink(xmlBufferPtr buf, unsigned int len) { + */ + int + xmlBufferGrow(xmlBufferPtr buf, unsigned int len) { +- int size; ++ unsigned int size; + xmlChar *newbuf; + + if (buf == NULL) return(-1); + + if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0); +- if (len + buf->use < buf->size) return(0); ++ if (len < buf->size - buf->use) ++ return(0); ++ if (len > UINT_MAX - buf->use) ++ return(-1); + +- /* +- * Windows has a BIG problem on realloc timing, so we try to double +- * the buffer size (if that's enough) (bug 146697) +- * Apparently BSD too, and it's probably best for linux too +- * On an embedded system this may be something to change +- */ +-#if 1 +- if (buf->size > len) +- size = buf->size * 2; +- else +- size = buf->use + len + 100; +-#else +- size = buf->use + len + 100; +-#endif ++ if (buf->size > (size_t) len) { ++ size = buf->size > UINT_MAX / 2 ? UINT_MAX : buf->size * 2; ++ } else { ++ size = buf->use + len; ++ size = size > UINT_MAX - 100 ? UINT_MAX : size + 100; ++ } + + if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) { + size_t start_buf = buf->content - buf->contentIO; +@@ -7466,7 +7465,10 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size) + case XML_BUFFER_ALLOC_IO: + case XML_BUFFER_ALLOC_DOUBLEIT: + /*take care of empty case*/ +- newSize = (buf->size ? buf->size : size + 10); ++ if (buf->size == 0) ++ newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10); ++ else ++ newSize = buf->size; + while (size > newSize) { + if (newSize > UINT_MAX / 2) { + xmlTreeErrMemory("growing buffer"); +@@ -7476,7 +7478,7 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size) + } + break; + case XML_BUFFER_ALLOC_EXACT: +- newSize = size+10; ++ newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);; + break; + case XML_BUFFER_ALLOC_HYBRID: + if (buf->use < BASE_BUFFER_SIZE) +@@ -7494,7 +7496,7 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size) + break; + + default: +- newSize = size+10; ++ newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);; + break; + } + +@@ -7580,8 +7582,10 @@ xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) { + if (len < 0) return -1; + if (len == 0) return 0; + +- needSize = buf->use + len + 2; +- if (needSize > buf->size){ ++ if ((unsigned) len >= buf->size - buf->use) { ++ if ((unsigned) len >= UINT_MAX - buf->use) ++ return XML_ERR_NO_MEMORY; ++ needSize = buf->use + len + 1; + if (!xmlBufferResize(buf, needSize)){ + xmlTreeErrMemory("growing buffer"); + return XML_ERR_NO_MEMORY; +@@ -7694,29 +7698,7 @@ xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) { + */ + int + xmlBufferCCat(xmlBufferPtr buf, const char *str) { +- const char *cur; +- +- if (buf == NULL) +- return(-1); +- if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1; +- if (str == NULL) { +-#ifdef DEBUG_BUFFER +- xmlGenericError(xmlGenericErrorContext, +- "xmlBufferCCat: str == NULL\n"); +-#endif +- return -1; +- } +- for (cur = str;*cur != 0;cur++) { +- if (buf->use + 10 >= buf->size) { +- if (!xmlBufferResize(buf, buf->use+10)){ +- xmlTreeErrMemory("growing buffer"); +- return XML_ERR_NO_MEMORY; +- } +- } +- buf->content[buf->use++] = *cur; +- } +- buf->content[buf->use] = 0; +- return 0; ++ return xmlBufferCat(buf, (const xmlChar *) str); + } + + /** +-- +GitLab + diff --git a/meta/recipes-core/libxml/libxml2/CVE-2022-40303.patch b/meta/recipes-core/libxml/libxml2/CVE-2022-40303.patch new file mode 100644 index 0000000000..bdb9e9eb7a --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2022-40303.patch @@ -0,0 +1,623 @@ +From c846986356fc149915a74972bf198abc266bc2c0 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Thu, 25 Aug 2022 17:43:08 +0200 +Subject: [PATCH] [CVE-2022-40303] Fix integer overflows with XML_PARSE_HUGE + +Also impose size limits when XML_PARSE_HUGE is set. Limit size of names +to XML_MAX_TEXT_LENGTH (10 million bytes) and other content to +XML_MAX_HUGE_LENGTH (1 billion bytes). + +Move some the length checks to the end of the respective loop to make +them strict. + +xmlParseEntityValue didn't have a length limitation at all. But without +XML_PARSE_HUGE, this should eventually trigger an error in xmlGROW. + +Thanks to Maddie Stone working with Google Project Zero for the report! + +CVE: CVE-2022-40303 +Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/c846986356fc149915a74972bf198abc266bc2c0] +Comments: Refreshed hunk + +Signed-off-by: Bhabu Bindu <bhabu.bindu@kpit.com> +--- + parser.c | 233 +++++++++++++++++++++++++++++-------------------------- + 1 file changed, 121 insertions(+), 112 deletions(-) + +diff --git a/parser.c b/parser.c +index 93f031be..79479979 100644 +--- a/parser.c ++++ b/parser.c +@@ -102,6 +102,8 @@ xmlParseElementEnd(xmlParserCtxtPtr ctxt); + * * + ************************************************************************/ + ++#define XML_MAX_HUGE_LENGTH 1000000000 ++ + #define XML_PARSER_BIG_ENTITY 1000 + #define XML_PARSER_LOT_ENTITY 5000 + +@@ -552,7 +554,7 @@ xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info) + errmsg = "Malformed declaration expecting version"; + break; + case XML_ERR_NAME_TOO_LONG: +- errmsg = "Name too long use XML_PARSE_HUGE option"; ++ errmsg = "Name too long"; + break; + #if 0 + case: +@@ -3202,6 +3204,9 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) { + int len = 0, l; + int c; + int count = 0; ++ int maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_TEXT_LENGTH : ++ XML_MAX_NAME_LENGTH; + + #ifdef DEBUG + nbParseNameComplex++; +@@ -3267,7 +3272,8 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) { + if (ctxt->instate == XML_PARSER_EOF) + return(NULL); + } +- len += l; ++ if (len <= INT_MAX - l) ++ len += l; + NEXTL(l); + c = CUR_CHAR(l); + } +@@ -3293,13 +3299,13 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) { + if (ctxt->instate == XML_PARSER_EOF) + return(NULL); + } +- len += l; ++ if (len <= INT_MAX - l) ++ len += l; + NEXTL(l); + c = CUR_CHAR(l); + } + } +- if ((len > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if (len > maxLength) { + xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name"); + return(NULL); + } +@@ -3338,7 +3344,10 @@ const xmlChar * + xmlParseName(xmlParserCtxtPtr ctxt) { + const xmlChar *in; + const xmlChar *ret; +- int count = 0; ++ size_t count = 0; ++ size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_TEXT_LENGTH : ++ XML_MAX_NAME_LENGTH; + + GROW; + +@@ -3362,8 +3371,7 @@ xmlParseName(xmlParserCtxtPtr ctxt) { + in++; + if ((*in > 0) && (*in < 0x80)) { + count = in - ctxt->input->cur; +- if ((count > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if (count > maxLength) { + xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name"); + return(NULL); + } +@@ -3384,6 +3392,9 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { + int len = 0, l; + int c; + int count = 0; ++ int maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_TEXT_LENGTH : ++ XML_MAX_NAME_LENGTH; + size_t startPosition = 0; + + #ifdef DEBUG +@@ -3404,17 +3415,13 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { + while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */ + (xmlIsNameChar(ctxt, c) && (c != ':'))) { + if (count++ > XML_PARSER_CHUNK_SIZE) { +- if ((len > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { +- xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName"); +- return(NULL); +- } + count = 0; + GROW; + if (ctxt->instate == XML_PARSER_EOF) + return(NULL); + } +- len += l; ++ if (len <= INT_MAX - l) ++ len += l; + NEXTL(l); + c = CUR_CHAR(l); + if (c == 0) { +@@ -3432,8 +3439,7 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { + c = CUR_CHAR(l); + } + } +- if ((len > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if (len > maxLength) { + xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName"); + return(NULL); + } +@@ -3459,7 +3465,10 @@ static const xmlChar * + xmlParseNCName(xmlParserCtxtPtr ctxt) { + const xmlChar *in, *e; + const xmlChar *ret; +- int count = 0; ++ size_t count = 0; ++ size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_TEXT_LENGTH : ++ XML_MAX_NAME_LENGTH; + + #ifdef DEBUG + nbParseNCName++; +@@ -3484,8 +3493,7 @@ xmlParseNCName(xmlParserCtxtPtr ctxt) { + goto complex; + if ((*in > 0) && (*in < 0x80)) { + count = in - ctxt->input->cur; +- if ((count > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if (count > maxLength) { + xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName"); + return(NULL); + } +@@ -3567,6 +3575,9 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) { + const xmlChar *cur = *str; + int len = 0, l; + int c; ++ int maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_TEXT_LENGTH : ++ XML_MAX_NAME_LENGTH; + + #ifdef DEBUG + nbParseStringName++; +@@ -3602,12 +3613,6 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) { + if (len + 10 > max) { + xmlChar *tmp; + +- if ((len > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { +- xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName"); +- xmlFree(buffer); +- return(NULL); +- } + max *= 2; + tmp = (xmlChar *) xmlRealloc(buffer, + max * sizeof(xmlChar)); +@@ -3621,14 +3626,18 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) { + COPY_BUF(l,buffer,len,c); + cur += l; + c = CUR_SCHAR(cur, l); ++ if (len > maxLength) { ++ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName"); ++ xmlFree(buffer); ++ return(NULL); ++ } + } + buffer[len] = 0; + *str = cur; + return(buffer); + } + } +- if ((len > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if (len > maxLength) { + xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName"); + return(NULL); + } +@@ -3655,6 +3664,9 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) { + int len = 0, l; + int c; + int count = 0; ++ int maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_TEXT_LENGTH : ++ XML_MAX_NAME_LENGTH; + + #ifdef DEBUG + nbParseNmToken++; +@@ -3706,12 +3718,6 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) { + if (len + 10 > max) { + xmlChar *tmp; + +- if ((max > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { +- xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken"); +- xmlFree(buffer); +- return(NULL); +- } + max *= 2; + tmp = (xmlChar *) xmlRealloc(buffer, + max * sizeof(xmlChar)); +@@ -3725,6 +3731,11 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) { + COPY_BUF(l,buffer,len,c); + NEXTL(l); + c = CUR_CHAR(l); ++ if (len > maxLength) { ++ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken"); ++ xmlFree(buffer); ++ return(NULL); ++ } + } + buffer[len] = 0; + return(buffer); +@@ -3732,8 +3743,7 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) { + } + if (len == 0) + return(NULL); +- if ((len > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if (len > maxLength) { + xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken"); + return(NULL); + } +@@ -3759,6 +3769,9 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) { + int len = 0; + int size = XML_PARSER_BUFFER_SIZE; + int c, l; ++ int maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_HUGE_LENGTH : ++ XML_MAX_TEXT_LENGTH; + xmlChar stop; + xmlChar *ret = NULL; + const xmlChar *cur = NULL; +@@ -3818,6 +3831,12 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) { + GROW; + c = CUR_CHAR(l); + } ++ ++ if (len > maxLength) { ++ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_NOT_FINISHED, ++ "entity value too long\n"); ++ goto error; ++ } + } + buf[len] = 0; + if (ctxt->instate == XML_PARSER_EOF) +@@ -3905,6 +3924,9 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { + xmlChar *rep = NULL; + size_t len = 0; + size_t buf_size = 0; ++ size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_HUGE_LENGTH : ++ XML_MAX_TEXT_LENGTH; + int c, l, in_space = 0; + xmlChar *current = NULL; + xmlEntityPtr ent; +@@ -3925,16 +3925,6 @@ + while (((NXT(0) != limit) && /* checked */ + (IS_CHAR(c)) && (c != '<')) && + (ctxt->instate != XML_PARSER_EOF)) { +- /* +- * Impose a reasonable limit on attribute size, unless XML_PARSE_HUGE +- * special option is given +- */ +- if ((len > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { +- xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, +- "AttValue length too long\n"); +- goto mem_error; +- } + if (c == 0) break; + if (c == '&') { + in_space = 0; +@@ -4093,6 +4105,11 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { + } + GROW; + c = CUR_CHAR(l); ++ if (len > maxLength) { ++ xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, ++ "AttValue length too long\n"); ++ goto mem_error; ++ } + } + if (ctxt->instate == XML_PARSER_EOF) + goto error; +@@ -4114,16 +4131,6 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { + } else + NEXT; + +- /* +- * There we potentially risk an overflow, don't allow attribute value of +- * length more than INT_MAX it is a very reasonable assumption ! +- */ +- if (len >= INT_MAX) { +- xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, +- "AttValue length too long\n"); +- goto mem_error; +- } +- + if (attlen != NULL) *attlen = (int) len; + return(buf); + +@@ -4194,6 +4201,9 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) { + int len = 0; + int size = XML_PARSER_BUFFER_SIZE; + int cur, l; ++ int maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_TEXT_LENGTH : ++ XML_MAX_NAME_LENGTH; + xmlChar stop; + int state = ctxt->instate; + int count = 0; +@@ -4221,13 +4231,6 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) { + if (len + 5 >= size) { + xmlChar *tmp; + +- if ((size > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { +- xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral"); +- xmlFree(buf); +- ctxt->instate = (xmlParserInputState) state; +- return(NULL); +- } + size *= 2; + tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); + if (tmp == NULL) { +@@ -4256,6 +4259,12 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) { + SHRINK; + cur = CUR_CHAR(l); + } ++ if (len > maxLength) { ++ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral"); ++ xmlFree(buf); ++ ctxt->instate = (xmlParserInputState) state; ++ return(NULL); ++ } + } + buf[len] = 0; + ctxt->instate = (xmlParserInputState) state; +@@ -4283,6 +4292,9 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) { + xmlChar *buf = NULL; + int len = 0; + int size = XML_PARSER_BUFFER_SIZE; ++ int maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_TEXT_LENGTH : ++ XML_MAX_NAME_LENGTH; + xmlChar cur; + xmlChar stop; + int count = 0; +@@ -4310,12 +4322,6 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) { + if (len + 1 >= size) { + xmlChar *tmp; + +- if ((size > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { +- xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID"); +- xmlFree(buf); +- return(NULL); +- } + size *= 2; + tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); + if (tmp == NULL) { +@@ -4343,6 +4349,11 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) { + SHRINK; + cur = CUR; + } ++ if (len > maxLength) { ++ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID"); ++ xmlFree(buf); ++ return(NULL); ++ } + } + buf[len] = 0; + if (cur != stop) { +@@ -4742,6 +4753,9 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf, + int r, rl; + int cur, l; + size_t count = 0; ++ size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_HUGE_LENGTH : ++ XML_MAX_TEXT_LENGTH; + int inputid; + + inputid = ctxt->input->id; +@@ -4787,13 +4801,6 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf, + if ((r == '-') && (q == '-')) { + xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL); + } +- if ((len > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { +- xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED, +- "Comment too big found", NULL); +- xmlFree (buf); +- return; +- } + if (len + 5 >= size) { + xmlChar *new_buf; + size_t new_size; +@@ -4831,6 +4838,13 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf, + GROW; + cur = CUR_CHAR(l); + } ++ ++ if (len > maxLength) { ++ xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED, ++ "Comment too big found", NULL); ++ xmlFree (buf); ++ return; ++ } + } + buf[len] = 0; + if (cur == 0) { +@@ -4875,6 +4889,9 @@ xmlParseComment(xmlParserCtxtPtr ctxt) { + xmlChar *buf = NULL; + size_t size = XML_PARSER_BUFFER_SIZE; + size_t len = 0; ++ size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_HUGE_LENGTH : ++ XML_MAX_TEXT_LENGTH; + xmlParserInputState state; + const xmlChar *in; + size_t nbchar = 0; +@@ -4958,8 +4975,7 @@ get_more: + buf[len] = 0; + } + } +- if ((len > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if (len > maxLength) { + xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED, + "Comment too big found", NULL); + xmlFree (buf); +@@ -5159,6 +5175,9 @@ xmlParsePI(xmlParserCtxtPtr ctxt) { + xmlChar *buf = NULL; + size_t len = 0; + size_t size = XML_PARSER_BUFFER_SIZE; ++ size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_HUGE_LENGTH : ++ XML_MAX_TEXT_LENGTH; + int cur, l; + const xmlChar *target; + xmlParserInputState state; +@@ -5234,14 +5253,6 @@ xmlParsePI(xmlParserCtxtPtr ctxt) { + return; + } + count = 0; +- if ((len > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { +- xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED, +- "PI %s too big found", target); +- xmlFree(buf); +- ctxt->instate = state; +- return; +- } + } + COPY_BUF(l,buf,len,cur); + NEXTL(l); +@@ -5251,15 +5262,14 @@ xmlParsePI(xmlParserCtxtPtr ctxt) { + GROW; + cur = CUR_CHAR(l); + } ++ if (len > maxLength) { ++ xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED, ++ "PI %s too big found", target); ++ xmlFree(buf); ++ ctxt->instate = state; ++ return; ++ } + } +- if ((len > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { +- xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED, +- "PI %s too big found", target); +- xmlFree(buf); +- ctxt->instate = state; +- return; +- } + buf[len] = 0; + if (cur != '?') { + xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED, +@@ -8954,6 +8964,9 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc, + const xmlChar *in = NULL, *start, *end, *last; + xmlChar *ret = NULL; + int line, col; ++ int maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_HUGE_LENGTH : ++ XML_MAX_TEXT_LENGTH; + + GROW; + in = (xmlChar *) CUR_PTR; +@@ -8993,8 +9006,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc, + start = in; + if (in >= end) { + GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end) +- if (((in - start) > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if ((in - start) > maxLength) { + xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, + "AttValue length too long\n"); + return(NULL); +@@ -9007,8 +9019,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc, + if ((*in++ == 0x20) && (*in == 0x20)) break; + if (in >= end) { + GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end) +- if (((in - start) > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if ((in - start) > maxLength) { + xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, + "AttValue length too long\n"); + return(NULL); +@@ -9041,16 +9052,14 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc, + last = last + delta; + } + end = ctxt->input->end; +- if (((in - start) > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if ((in - start) > maxLength) { + xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, + "AttValue length too long\n"); + return(NULL); + } + } + } +- if (((in - start) > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if ((in - start) > maxLength) { + xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, + "AttValue length too long\n"); + return(NULL); +@@ -9063,8 +9072,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc, + col++; + if (in >= end) { + GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end) +- if (((in - start) > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if ((in - start) > maxLength) { + xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, + "AttValue length too long\n"); + return(NULL); +@@ -9072,8 +9080,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc, + } + } + last = in; +- if (((in - start) > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if ((in - start) > maxLength) { + xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, + "AttValue length too long\n"); + return(NULL); +@@ -9763,6 +9770,9 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) { + int s, sl; + int cur, l; + int count = 0; ++ int maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_HUGE_LENGTH : ++ XML_MAX_TEXT_LENGTH; + + /* Check 2.6.0 was NXT(0) not RAW */ + if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) { +@@ -9796,13 +9806,6 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) { + if (len + 5 >= size) { + xmlChar *tmp; + +- if ((size > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { +- xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED, +- "CData section too big found", NULL); +- xmlFree (buf); +- return; +- } + tmp = (xmlChar *) xmlRealloc(buf, size * 2 * sizeof(xmlChar)); + if (tmp == NULL) { + xmlFree(buf); +@@ -9829,6 +9832,12 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) { + } + NEXTL(l); + cur = CUR_CHAR(l); ++ if (len > maxLength) { ++ xmlFatalErrMsg(ctxt, XML_ERR_CDATA_NOT_FINISHED, ++ "CData section too big found\n"); ++ xmlFree(buf); ++ return; ++ } + } + buf[len] = 0; + ctxt->instate = XML_PARSER_CONTENT; +-- +GitLab diff --git a/meta/recipes-core/libxml/libxml2/CVE-2022-40304.patch b/meta/recipes-core/libxml/libxml2/CVE-2022-40304.patch new file mode 100644 index 0000000000..c19726fe9f --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2022-40304.patch @@ -0,0 +1,104 @@ +From 1b41ec4e9433b05bb0376be4725804c54ef1d80b Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Wed, 31 Aug 2022 22:11:25 +0200 +Subject: [PATCH] [CVE-2022-40304] Fix dict corruption caused by entity + reference cycles + +When an entity reference cycle is detected, the entity content is +cleared by setting its first byte to zero. But the entity content might +be allocated from a dict. In this case, the dict entry becomes corrupted +leading to all kinds of logic errors, including memory errors like +double-frees. + +Stop storing entity content, orig, ExternalID and SystemID in a dict. +These values are unlikely to occur multiple times in a document, so they +shouldn't have been stored in a dict in the first place. + +Thanks to Ned Williamson and Nathan Wachholz working with Google Project +Zero for the report! + +CVE: CVE-2022-40304 +Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/1b41ec4e9433b05bb0376be4725804c54ef1d80b] +Signed-off-by: Bhabu Bindu <bhabu.bindu@kpit.com> +--- + entities.c | 55 ++++++++++++++++-------------------------------------- + 1 file changed, 16 insertions(+), 39 deletions(-) + +diff --git a/entities.c b/entities.c +index 84435515..d4e5412e 100644 +--- a/entities.c ++++ b/entities.c +@@ -128,36 +128,19 @@ xmlFreeEntity(xmlEntityPtr entity) + if ((entity->children) && (entity->owner == 1) && + (entity == (xmlEntityPtr) entity->children->parent)) + xmlFreeNodeList(entity->children); +- if (dict != NULL) { +- if ((entity->name != NULL) && (!xmlDictOwns(dict, entity->name))) +- xmlFree((char *) entity->name); +- if ((entity->ExternalID != NULL) && +- (!xmlDictOwns(dict, entity->ExternalID))) +- xmlFree((char *) entity->ExternalID); +- if ((entity->SystemID != NULL) && +- (!xmlDictOwns(dict, entity->SystemID))) +- xmlFree((char *) entity->SystemID); +- if ((entity->URI != NULL) && (!xmlDictOwns(dict, entity->URI))) +- xmlFree((char *) entity->URI); +- if ((entity->content != NULL) +- && (!xmlDictOwns(dict, entity->content))) +- xmlFree((char *) entity->content); +- if ((entity->orig != NULL) && (!xmlDictOwns(dict, entity->orig))) +- xmlFree((char *) entity->orig); +- } else { +- if (entity->name != NULL) +- xmlFree((char *) entity->name); +- if (entity->ExternalID != NULL) +- xmlFree((char *) entity->ExternalID); +- if (entity->SystemID != NULL) +- xmlFree((char *) entity->SystemID); +- if (entity->URI != NULL) +- xmlFree((char *) entity->URI); +- if (entity->content != NULL) +- xmlFree((char *) entity->content); +- if (entity->orig != NULL) +- xmlFree((char *) entity->orig); +- } ++ if ((entity->name != NULL) && ++ ((dict == NULL) || (!xmlDictOwns(dict, entity->name)))) ++ xmlFree((char *) entity->name); ++ if (entity->ExternalID != NULL) ++ xmlFree((char *) entity->ExternalID); ++ if (entity->SystemID != NULL) ++ xmlFree((char *) entity->SystemID); ++ if (entity->URI != NULL) ++ xmlFree((char *) entity->URI); ++ if (entity->content != NULL) ++ xmlFree((char *) entity->content); ++ if (entity->orig != NULL) ++ xmlFree((char *) entity->orig); + xmlFree(entity); + } + +@@ -193,18 +176,12 @@ xmlCreateEntity(xmlDictPtr dict, const xmlChar *name, int type, + ret->SystemID = xmlStrdup(SystemID); + } else { + ret->name = xmlDictLookup(dict, name, -1); +- if (ExternalID != NULL) +- ret->ExternalID = xmlDictLookup(dict, ExternalID, -1); +- if (SystemID != NULL) +- ret->SystemID = xmlDictLookup(dict, SystemID, -1); ++ ret->ExternalID = xmlStrdup(ExternalID); ++ ret->SystemID = xmlStrdup(SystemID); + } + if (content != NULL) { + ret->length = xmlStrlen(content); +- if ((dict != NULL) && (ret->length < 5)) +- ret->content = (xmlChar *) +- xmlDictLookup(dict, content, ret->length); +- else +- ret->content = xmlStrndup(content, ret->length); ++ ret->content = xmlStrndup(content, ret->length); + } else { + ret->length = 0; + ret->content = NULL; +-- +GitLab diff --git a/meta/recipes-core/libxml/libxml2/CVE-2023-28484.patch b/meta/recipes-core/libxml/libxml2/CVE-2023-28484.patch new file mode 100644 index 0000000000..907f2c4d47 --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2023-28484.patch @@ -0,0 +1,79 @@ +From e4f85f1bd2eb34d9b49da9154a4cc3a1bc284f68 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Fri, 7 Apr 2023 11:46:35 +0200 +Subject: [PATCH] [CVE-2023-28484] Fix null deref in xmlSchemaFixupComplexType + +Fix a null pointer dereference when parsing (invalid) XML schemas. + +Thanks to Robby Simpson for the report! + +Fixes #491. + +CVE: CVE-2023-28484 +Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/e4f85f1bd2eb34d9b49da9154a4cc3a1bc284f68] + +Signed-off-by: Peter Marko <peter.marko@siemens.com> +--- + result/schemas/issue491_0_0.err | 1 + + test/schemas/issue491_0.xml | 1 + + test/schemas/issue491_0.xsd | 18 ++++++++++++++++++ + xmlschemas.c | 2 +- + 4 files changed, 21 insertions(+), 1 deletion(-) + create mode 100644 result/schemas/issue491_0_0.err + create mode 100644 test/schemas/issue491_0.xml + create mode 100644 test/schemas/issue491_0.xsd + +diff --git a/result/schemas/issue491_0_0.err b/result/schemas/issue491_0_0.err +new file mode 100644 +index 00000000..9b2bb969 +--- /dev/null ++++ b/result/schemas/issue491_0_0.err +@@ -0,0 +1 @@ ++./test/schemas/issue491_0.xsd:8: element complexType: Schemas parser error : complex type 'ChildType': The content type of both, the type and its base type, must either 'mixed' or 'element-only'. +diff --git a/test/schemas/issue491_0.xml b/test/schemas/issue491_0.xml +new file mode 100644 +index 00000000..e2b2fc2e +--- /dev/null ++++ b/test/schemas/issue491_0.xml +@@ -0,0 +1 @@ ++<Child xmlns="http://www.test.com">5</Child> +diff --git a/test/schemas/issue491_0.xsd b/test/schemas/issue491_0.xsd +new file mode 100644 +index 00000000..81702649 +--- /dev/null ++++ b/test/schemas/issue491_0.xsd +@@ -0,0 +1,18 @@ ++<?xml version='1.0' encoding='UTF-8'?> ++<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.test.com" targetNamespace="http://www.test.com" elementFormDefault="qualified" attributeFormDefault="unqualified"> ++ <xs:complexType name="BaseType"> ++ <xs:simpleContent> ++ <xs:extension base="xs:int" /> ++ </xs:simpleContent> ++ </xs:complexType> ++ <xs:complexType name="ChildType"> ++ <xs:complexContent> ++ <xs:extension base="BaseType"> ++ <xs:sequence> ++ <xs:element name="bad" type="xs:int" minOccurs="0" maxOccurs="1"/> ++ </xs:sequence> ++ </xs:extension> ++ </xs:complexContent> ++ </xs:complexType> ++ <xs:element name="Child" type="ChildType" /> ++</xs:schema> +diff --git a/xmlschemas.c b/xmlschemas.c +index 6a353858..a4eaf591 100644 +--- a/xmlschemas.c ++++ b/xmlschemas.c +@@ -18632,7 +18632,7 @@ xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt, + "allowed to appear inside other model groups", + NULL, NULL); + +- } else if (! dummySequence) { ++ } else if ((!dummySequence) && (baseType->subtypes != NULL)) { + xmlSchemaTreeItemPtr effectiveContent = + (xmlSchemaTreeItemPtr) type->subtypes; + /* +-- +GitLab + diff --git a/meta/recipes-core/libxml/libxml2/CVE-2023-29469.patch b/meta/recipes-core/libxml/libxml2/CVE-2023-29469.patch new file mode 100644 index 0000000000..1252668577 --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2023-29469.patch @@ -0,0 +1,42 @@ +From 547edbf1cbdccd46b2e8ff322a456eaa5931c5df Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Fri, 7 Apr 2023 11:49:27 +0200 +Subject: [PATCH] [CVE-2023-29469] Hashing of empty dict strings isn't + deterministic + +When hashing empty strings which aren't null-terminated, +xmlDictComputeFastKey could produce inconsistent results. This could +lead to various logic or memory errors, including double frees. + +For consistency the seed is also taken into account, but this shouldn't +have an impact on security. + +Found by OSS-Fuzz. + +Fixes #510. + +CVE: CVE-2023-29469 +Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/547edbf1cbdccd46b2e8ff322a456eaa5931c5df] + +Signed-off-by: Peter Marko <peter.marko@siemens.com> +--- + dict.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/dict.c b/dict.c +index 86c3f6d7..d7fd1a06 100644 +--- a/dict.c ++++ b/dict.c +@@ -451,7 +451,8 @@ static unsigned long + xmlDictComputeFastKey(const xmlChar *name, int namelen, int seed) { + unsigned long value = seed; + +- if (name == NULL) return(0); ++ if ((name == NULL) || (namelen <= 0)) ++ return(value); + value = *name; + value <<= 5; + if (namelen > 10) { +-- +GitLab + diff --git a/meta/recipes-core/libxml/libxml2/CVE-2023-39615-0001.patch b/meta/recipes-core/libxml/libxml2/CVE-2023-39615-0001.patch new file mode 100644 index 0000000000..9689cec67d --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2023-39615-0001.patch @@ -0,0 +1,36 @@ +From d0c3f01e110d54415611c5fa0040cdf4a56053f9 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Sat, 6 May 2023 17:47:37 +0200 +Subject: [PATCH] parser: Fix old SAX1 parser with custom callbacks + +For some reason, xmlCtxtUseOptionsInternal set the start and end element +SAX handlers to the internal DOM builder functions when XML_PARSE_SAX1 +was specified. This means that custom SAX handlers could never work with +that flag because these functions would receive the wrong user data +argument and crash immediately. + +Fixes #535. + +Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/libxml2/-/commit/d0c3f01e110d54415611c5fa0040cdf4a56053f9] +CVE: CVE-2023-39615 +Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> +--- + parser.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/parser.c b/parser.c +index 6e09208..7814e6e 100644 +--- a/parser.c ++++ b/parser.c +@@ -15156,8 +15156,6 @@ xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encodi + } + #ifdef LIBXML_SAX1_ENABLED + if (options & XML_PARSE_SAX1) { +- ctxt->sax->startElement = xmlSAX2StartElement; +- ctxt->sax->endElement = xmlSAX2EndElement; + ctxt->sax->startElementNs = NULL; + ctxt->sax->endElementNs = NULL; + ctxt->sax->initialized = 1; +-- +2.24.4 + diff --git a/meta/recipes-core/libxml/libxml2/CVE-2023-39615-0002.patch b/meta/recipes-core/libxml/libxml2/CVE-2023-39615-0002.patch new file mode 100644 index 0000000000..ebd9868fac --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2023-39615-0002.patch @@ -0,0 +1,71 @@ +From 235b15a590eecf97b09e87bdb7e4f8333e9de129 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Mon, 8 May 2023 17:58:02 +0200 +Subject: [PATCH] SAX: Always initialize SAX1 element handlers + +Follow-up to commit d0c3f01e. A parser context will be initialized to +SAX version 2, but this can be overridden with XML_PARSE_SAX1 later, +so we must initialize the SAX1 element handlers as well. + +Change the check in xmlDetectSAX2 to only look for XML_SAX2_MAGIC, so +we don't switch to SAX1 if the SAX2 element handlers are NULL. + +Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/libxml2/-/commit/235b15a590eecf97b09e87bdb7e4f8333e9de129] +CVE: CVE-2023-39615 +Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> +--- + SAX2.c | 11 +++++++---- + parser.c | 5 +---- + 2 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/SAX2.c b/SAX2.c +index 5f141f9..902d34d 100644 +--- a/SAX2.c ++++ b/SAX2.c +@@ -2869,20 +2869,23 @@ xmlSAXVersion(xmlSAXHandler *hdlr, int version) + { + if (hdlr == NULL) return(-1); + if (version == 2) { +- hdlr->startElement = NULL; +- hdlr->endElement = NULL; + hdlr->startElementNs = xmlSAX2StartElementNs; + hdlr->endElementNs = xmlSAX2EndElementNs; + hdlr->serror = NULL; + hdlr->initialized = XML_SAX2_MAGIC; + #ifdef LIBXML_SAX1_ENABLED + } else if (version == 1) { +- hdlr->startElement = xmlSAX2StartElement; +- hdlr->endElement = xmlSAX2EndElement; + hdlr->initialized = 1; + #endif /* LIBXML_SAX1_ENABLED */ + } else + return(-1); ++#ifdef LIBXML_SAX1_ENABLED ++ hdlr->startElement = xmlSAX2StartElement; ++ hdlr->endElement = xmlSAX2EndElement; ++#else ++ hdlr->startElement = NULL; ++ hdlr->endElement = NULL; ++#endif /* LIBXML_SAX1_ENABLED */ + hdlr->internalSubset = xmlSAX2InternalSubset; + hdlr->externalSubset = xmlSAX2ExternalSubset; + hdlr->isStandalone = xmlSAX2IsStandalone; +diff --git a/parser.c b/parser.c +index 7814e6e..cf0fb38 100644 +--- a/parser.c ++++ b/parser.c +@@ -1102,10 +1102,7 @@ xmlDetectSAX2(xmlParserCtxtPtr ctxt) { + if (ctxt == NULL) return; + sax = ctxt->sax; + #ifdef LIBXML_SAX1_ENABLED +- if ((sax) && (sax->initialized == XML_SAX2_MAGIC) && +- ((sax->startElementNs != NULL) || +- (sax->endElementNs != NULL) || +- ((sax->startElement == NULL) && (sax->endElement == NULL)))) ++ if ((sax) && (sax->initialized == XML_SAX2_MAGIC)) + ctxt->sax2 = 1; + #else + ctxt->sax2 = 1; +-- +2.24.4 + diff --git a/meta/recipes-core/libxml/libxml2/CVE-2023-39615-pre.patch b/meta/recipes-core/libxml/libxml2/CVE-2023-39615-pre.patch new file mode 100644 index 0000000000..b177cdaba0 --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2023-39615-pre.patch @@ -0,0 +1,44 @@ +From 99fc048d7f7292c5ee18e44c400bd73bc63a47ed Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Fri, 14 Aug 2020 14:18:50 +0200 +Subject: [PATCH] Don't use SAX1 if all element handlers are NULL + +Running xmllint with "--sax --noout" installs a SAX2 handler with all +callbacks set to NULL. In this case or similar situations, we don't want +to switch to SAX1 parsing. + +Note: This patch is needed for "CVE-2023-39615-0002" patch to apply. +Without this patch the build will fail with undefined sax error. + +Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/libxml2/-/commit/99fc048d7f7292c5ee18e44c400bd73bc63a47ed] +Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> +--- + parser.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/parser.c b/parser.c +index bb677b0..6e09208 100644 +--- a/parser.c ++++ b/parser.c +@@ -1098,11 +1098,15 @@ xmlHasFeature(xmlFeature feature) + */ + static void + xmlDetectSAX2(xmlParserCtxtPtr ctxt) { ++ xmlSAXHandlerPtr sax; + if (ctxt == NULL) return; ++ sax = ctxt->sax; + #ifdef LIBXML_SAX1_ENABLED +- if ((ctxt->sax) && (ctxt->sax->initialized == XML_SAX2_MAGIC) && +- ((ctxt->sax->startElementNs != NULL) || +- (ctxt->sax->endElementNs != NULL))) ctxt->sax2 = 1; ++ if ((sax) && (sax->initialized == XML_SAX2_MAGIC) && ++ ((sax->startElementNs != NULL) || ++ (sax->endElementNs != NULL) || ++ ((sax->startElement == NULL) && (sax->endElement == NULL)))) ++ ctxt->sax2 = 1; + #else + ctxt->sax2 = 1; + #endif /* LIBXML_SAX1_ENABLED */ +-- +2.24.4 + diff --git a/meta/recipes-core/libxml/libxml2/CVE-2023-45322-1.patch b/meta/recipes-core/libxml/libxml2/CVE-2023-45322-1.patch new file mode 100644 index 0000000000..182bb29abd --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2023-45322-1.patch @@ -0,0 +1,50 @@ +From a22bd982bf10291deea8ba0c61bf75b898c604ce Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Wed, 2 Nov 2022 15:44:42 +0100 +Subject: [PATCH] malloc-fail: Fix memory leak in xmlStaticCopyNodeList + +Found with libFuzzer, see #344. + +Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/a22bd982bf10291deea8ba0c61bf75b898c604ce] + +Signed-off-by: Peter Marko <peter.marko@siemens.com> +Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> +--- + tree.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/tree.c b/tree.c +index 507869efe..647288ce3 100644 +--- a/tree.c ++++ b/tree.c +@@ -4461,7 +4461,7 @@ xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) { + } + if (doc->intSubset == NULL) { + q = (xmlNodePtr) xmlCopyDtd( (xmlDtdPtr) node ); +- if (q == NULL) return(NULL); ++ if (q == NULL) goto error; + q->doc = doc; + q->parent = parent; + doc->intSubset = (xmlDtdPtr) q; +@@ -4473,7 +4473,7 @@ xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) { + } else + #endif /* LIBXML_TREE_ENABLED */ + q = xmlStaticCopyNode(node, doc, parent, 1); +- if (q == NULL) return(NULL); ++ if (q == NULL) goto error; + if (ret == NULL) { + q->prev = NULL; + ret = p = q; +@@ -4486,6 +4486,9 @@ xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) { + node = node->next; + } + return(ret); ++error: ++ xmlFreeNodeList(ret); ++ return(NULL); + } + + /** +-- +GitLab + diff --git a/meta/recipes-core/libxml/libxml2/CVE-2023-45322-2.patch b/meta/recipes-core/libxml/libxml2/CVE-2023-45322-2.patch new file mode 100644 index 0000000000..c7e9681e6a --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2023-45322-2.patch @@ -0,0 +1,80 @@ +From d39f78069dff496ec865c73aa44d7110e429bce9 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Wed, 23 Aug 2023 20:24:24 +0200 +Subject: [PATCH] tree: Fix copying of DTDs + +- Don't create multiple DTD nodes. +- Fix UAF if malloc fails. +- Skip DTD nodes if tree module is disabled. + +Fixes #583. + +CVE: CVE-2023-45322 +Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/d39f78069dff496ec865c73aa44d7110e429bce9] + +Signed-off-by: Peter Marko <peter.marko@siemens.com> +Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> +--- + tree.c | 31 ++++++++++++++++--------------- + 1 file changed, 16 insertions(+), 15 deletions(-) + +diff --git a/tree.c b/tree.c +index 6c8a875b9..02c1b5791 100644 +--- a/tree.c ++++ b/tree.c +@@ -4471,29 +4471,28 @@ xmlNodePtr + xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) { + xmlNodePtr ret = NULL; + xmlNodePtr p = NULL,q; ++ xmlDtdPtr newSubset = NULL; + + while (node != NULL) { +-#ifdef LIBXML_TREE_ENABLED + if (node->type == XML_DTD_NODE ) { +- if (doc == NULL) { ++#ifdef LIBXML_TREE_ENABLED ++ if ((doc == NULL) || (doc->intSubset != NULL)) { + node = node->next; + continue; + } +- if (doc->intSubset == NULL) { +- q = (xmlNodePtr) xmlCopyDtd( (xmlDtdPtr) node ); +- if (q == NULL) goto error; +- q->doc = doc; +- q->parent = parent; +- doc->intSubset = (xmlDtdPtr) q; +- xmlAddChild(parent, q); +- } else { +- q = (xmlNodePtr) doc->intSubset; +- xmlAddChild(parent, q); +- } +- } else ++ q = (xmlNodePtr) xmlCopyDtd( (xmlDtdPtr) node ); ++ if (q == NULL) goto error; ++ q->doc = doc; ++ q->parent = parent; ++ newSubset = (xmlDtdPtr) q; ++#else ++ node = node->next; ++ continue; + #endif /* LIBXML_TREE_ENABLED */ ++ } else { + q = xmlStaticCopyNode(node, doc, parent, 1); +- if (q == NULL) goto error; ++ if (q == NULL) goto error; ++ } + if (ret == NULL) { + q->prev = NULL; + ret = p = q; +@@ -4505,6 +4504,8 @@ xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) { + } + node = node->next; + } ++ if (newSubset != NULL) ++ doc->intSubset = newSubset; + return(ret); + error: + xmlFreeNodeList(ret); +-- +GitLab + diff --git a/meta/recipes-core/libxml/libxml2/CVE-2024-25062-pre1.patch b/meta/recipes-core/libxml/libxml2/CVE-2024-25062-pre1.patch new file mode 100644 index 0000000000..31183399f8 --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2024-25062-pre1.patch @@ -0,0 +1,38 @@ +From 31c6ce3b63f8a494ad9e31ca65187a73d8ad3508 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Mon, 9 Nov 2020 17:55:44 +0100 +Subject: [PATCH] Avoid call stack overflow with XML reader and recursive + XIncludes + +Don't process XIncludes in the result of another inclusion to avoid +infinite recursion resulting in a call stack overflow. + +This is something the XInclude engine shouldn't allow but correct +handling of intra-document includes would require major changes. + +Found by OSS-Fuzz. + +Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/31c6ce3b63f8a494ad9e31ca65187a73d8ad3508] +CVE: CVE-2024-25062 #Dependency Patch +Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> +--- + xmlreader.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/xmlreader.c b/xmlreader.c +index 01adf74f4..72e40b032 100644 +--- a/xmlreader.c ++++ b/xmlreader.c +@@ -1585,7 +1585,8 @@ node_found: + /* + * Handle XInclude if asked for + */ +- if ((reader->xinclude) && (reader->node != NULL) && ++ if ((reader->xinclude) && (reader->in_xinclude == 0) && ++ (reader->node != NULL) && + (reader->node->type == XML_ELEMENT_NODE) && + (reader->node->ns != NULL) && + ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) || +-- +GitLab + diff --git a/meta/recipes-core/libxml/libxml2/CVE-2024-25062.patch b/meta/recipes-core/libxml/libxml2/CVE-2024-25062.patch new file mode 100644 index 0000000000..5365d5546a --- /dev/null +++ b/meta/recipes-core/libxml/libxml2/CVE-2024-25062.patch @@ -0,0 +1,33 @@ +From 2b0aac140d739905c7848a42efc60bfe783a39b7 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Sat, 14 Oct 2023 22:45:54 +0200 +Subject: [PATCH] [CVE-2024-25062] xmlreader: Don't expand XIncludes when + backtracking + +Fixes a use-after-free if XML Reader if used with DTD validation and +XInclude expansion. + +Fixes #604. + +Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/2b0aac140d739905c7848a42efc60bfe783a39b7] +CVE: CVE-2024-25062 +Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> +--- + xmlreader.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/xmlreader.c b/xmlreader.c +index 979385a13..fefd68e0b 100644 +--- a/xmlreader.c ++++ b/xmlreader.c +@@ -1443,6 +1443,7 @@ node_found: + * Handle XInclude if asked for + */ + if ((reader->xinclude) && (reader->in_xinclude == 0) && ++ (reader->state != XML_TEXTREADER_BACKTRACK) && + (reader->node != NULL) && + (reader->node->type == XML_ELEMENT_NODE) && + (reader->node->ns != NULL) && +-- +GitLab + |