Repository navigation
Multiple segmentation faults in CPython's XML module #160497
Copy link
Copy link
Closed as not planned
Labels
type-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump
Description
Crash report
Bug Description
During differential fuzz testing of CPython and PyPy, we observed segmentation faults in CPython involving several XML-related standard library APIs.
The five cases involve xml.etree.ElementPath.iterfind() and the find(), findall(), findtext(), and iterfind() methods of xml.etree.ElementTree.Element. As, all five cases involve unusually long XPath expressions, ranging from approximately 400,000 to 880,000 characters, we are reporting them together.
Environment
- CPython: 3.11.11
- OS: Ubuntu 24.04.3 LTS
Reproduction Cases
The following reproduction programs reconstruct the long XPath strings from the available fuzzing records. Case 2 and 3 shows maximum recursion depth exceeded exception in the newest 3.11.17; rest segmentation faults still exists in 3.11.17.
Case 1: xml.etree.ElementPath.iterfind
import xml.etree.ElementPath as EP
from xml.dom import minidom
element1 = minidom.Element("45")
prefix = (
"<function dataclass.<locals>.wrap at 0x72ab51083a60>"
"<function dataclass.<locals>.wrap at 0x72ab51083a60>"
"<function dataclass.<locals>.wrap at 0x72ab51083a60>"
"<function dataclass.<locals>.wrap"
)
pattern = "<function dataclass.<locals>.wrap at 0x72ab51083a60>"
TARGET_LEN = 502_443
arg = prefix
needed = TARGET_LEN - len(arg)
if needed > 0:
reps = (needed // len(pattern)) + 3
arg += pattern * reps
arg = arg[:TARGET_LEN]
args = [element1, arg]
print("Length:", len(arg))
assert len(arg) == TARGET_LEN
print("Calling ElementPath.iterfind(...) …")
try:
result = list(EP.iterfind(*args))
print("Success – result size:", len(result))
except Exception as e:
print("Exception during iterfind:", e)Case 2: xml.etree.ElementTree.Element.findall
import xml.etree.ElementTree as ET
tag = "str_969"
attrib = {}
element = ET.Element(tag, attrib)
pattern = (
"<function no_type_check_decorator.<locals>.wrapped_decorator "
"at 0x7357ba2d3f60>"
)
TARGET_LEN = 449_520
prefix = (
"'<function no_type_check_decorator.<locals>.wrapped_decorator at 0x7357ba2d3f60>"
"<function no_type_check_decorator.<locals>.wrapped_decorator at 0x7357ba2d3f60>"
"<function no_type_check_decorator.<local"
)
arg = prefix
needed = TARGET_LEN - len(arg)
if needed > 0:
reps = (needed // len(pattern)) + 2
arg += pattern * reps
arg = arg[:TARGET_LEN]
method_args = [arg]
print("Length of method_args[0]:", len(method_args[0])) # Should be 449520
try:
print("Calling findall() ...")
result = element.findall(method_args[0])
print("Success:", result)
except Exception as e:
print("Exception during findall:", e)Case 3: xml.etree.ElementTree.Element.find
import xml.etree.ElementTree as ET
tag = "str_72"
attrib = {
"str_622": "str_821",
"str_783": "str_979",
}
element = ET.Element(tag, attrib)
prefix = (
"<function no_type_check_decorator.<locals>.wrapped_decorator at 0x77d93df57a60>"
"<function no_type_check_decorator.<locals>.wrapped_decorator at 0x77d93df57a60>"
"<function no_type_check_decorator.<locals>.wrapped_decorator at 0x77d93df57a60>"
"<function no_type_check_decorator.<locals>.wrapped_decorator"
)
pattern = (
"<function no_type_check_decorator.<locals>.wrapped_decorator "
"at 0x77d93df57a60>"
)
TARGET_LEN = 404_569
arg = prefix
needed = TARGET_LEN - len(arg)
if needed > 0:
reps = (needed // len(pattern)) + 3
arg += pattern * reps
arg = arg[:TARGET_LEN]
method_args = [arg]
print("Length:", len(method_args[0])) # Should print 404569
assert len(method_args[0]) == TARGET_LEN
print("Calling find() …")
try:
result = element.find(method_args[0])
print("find() returned:", result)
except Exception as e:
print("Exception during find():", e)Case 4: xml.etree.ElementTree.Element.findtext
import xml.etree.ElementTree as ET
tag = "str_18"
attrib = {
"str_24": "str_279",
"str_189": "str_807"
}
element = ET.Element(tag, attrib)
prefix = (
"+/v/\\U000e0062G\ufffdst\ufffd_128\\U0009f021\\x0b\ufffd\\uffff\ufffd"
"\\U000e005d\ufffd-1+/v/\\U000e0062G\ufffdst\ufffd_128\\U0009f021\\x0b"
"\ufffd\\uffff\ufffd\\U000e005d\ufffd-1+/v/\\U000e0062G\ufffdst\ufffd_128"
"\\U0009f021\\x0b\ufffd\\uffff\ufffd\\U000e005d\ufffd-1+/v/\\U000e0062G"
"\ufffdst\ufffd_128\\U0009f021\\x0b\ufffd\\uffff\ufffd\\U000e005d\ufffd-1+/v/"
)
pattern = (
"+/v/\U000e0062G\ufffdst\ufffd_128\U0009f021\x0b\ufffd\uffff\ufffd"
"\U000e005d\ufffd-1"
)
TARGET_LEN = 459_202
arg = prefix
needed = TARGET_LEN - len(arg)
if needed > 0:
reps = (needed // len(pattern)) + 3
arg += pattern * reps
arg = arg[:TARGET_LEN]
method_args = [arg]
print("Length:", len(method_args[0]))
assert len(method_args[0]) == TARGET_LEN
try:
print("Calling findtext()...")
result = element.findtext(method_args[0])
print("Success:", result)
except Exception as e:
print("Exception during findtext:", e)Case 5: xml.etree.ElementTree.Element.iterfind
import xml.etree.ElementTree as ET
tag = "str_288"
attrib = {
"str_861": "str_965",
"str_968": "str_343",
"str_163": "str_4",
"str_775": "str_468",
"str_71": "str_347",
}
element = ET.Element(tag, attrib)
pattern = (
"\rLeve\ufffd\ufffd\U000e0042\ufffd\ufffd\ufffd\ufffd"
"1\ufffd3\ufffd\ufffd\u202a3+/v9223372036854693041"
)
TARGET_LEN = 879_882
repetitions = (TARGET_LEN // len(pattern)) + 2
big_string = pattern * repetitions
big_string = big_string[:TARGET_LEN]
method_args = [big_string]
print("Length of method_args[0]:", len(method_args[0]))
print("Calling iterfind() ...")
try:
result = list(element.iterfind(method_args[0]))
print("Success – result length:", len(result))
except Exception as e:
print("Exception during iterfind:", e)CPython versions tested on:
3.11
Operating systems tested on:
Linux
Output from running 'python -VV' on the command line:
No response
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
type-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump
Activity
encukou commentedon Oct 23, 2026
None of these crash on 3.12+.
Python 3.11 now no longer accepts bugfixes, so I'll close this.
zahinwahab commentedon Oct 23, 2026
Thank you so much for the quick response!