Loading scripts/parse_sanitizer_errors_from_xml_report.py +65 −8 Original line number Diff line number Diff line #!/usr/env python3 from numpy import trace import pandas as pd from xml.etree import ElementTree import argparse Loading Loading @@ -78,6 +79,44 @@ class MsanError(SanitizerError): SUMMARY_ID = "MemorySanitizer" class AsanError(SanitizerError): SUMMARY_ID = "AddressSanitizer" def parse_type_and_location(self, traceback, cwd) -> Tuple[str, str]: first_line = traceback.split("\n")[0].strip() type = "" location = "" if "AddressSanitizer" in first_line: last_line = traceback.split("\n")[-1].strip() assert last_line.startswith(f"SUMMARY: {self.SUMMARY_ID}") m = re.match( r"SUMMARY: " + self.SUMMARY_ID + r": ([a-z-]*) (.*\/.*\.[ch]:\d+:\d+) in", last_line, ) assert m is not None type, location = m.groups() elif "LeakSanitizer" in first_line: type = "memory leaks" # for location, we just pick from the first leak, even if there are more in there # perfect accurac not needed here for line in traceback.split("\n"): # this assumes that number #0 always is the executable itself and has no file associated if line.strip().startswith("#1"): location = line.split()[-1] break else: raise NotImplementedError("Unknown Asan type") if Path(location).is_absolute(): location = str(Path(location).relative_to(cwd)) return type, location def parse_commandlines_from_sysout(sysout: str, cwd: Path) -> dict: commandlines = { "IVAS_cod": "", Loading @@ -92,17 +131,19 @@ def parse_commandlines_from_sysout(sysout: str, cwd: Path) -> dict: # search for name of executable in line # it is repeated in the sanitizer traceback, hence the "not in" part # the "not at the start" condition is for eid-xor (there are also lines like this: "eid-xor command:") # the "does not contain CalledProcessError" is for the renderer tests if ( re.search(exe, line) is not None and " in _start " not in line and not line.strip().startswith(exe) and "CalledProcessError" not in line ): if commandlines[exe] != "": logging.debug( f"Commandline for {exe} already found, skip second one." ) else: commandlines[exe] = postprocess_cmdline(line.strip(), cwd) commandlines[exe] = postprocess_cmdline(line.strip(), cwd, exe) # assumption: only one commandline per line break Loading @@ -110,8 +151,15 @@ def parse_commandlines_from_sysout(sysout: str, cwd: Path) -> dict: return commandlines def postprocess_cmdline(cmdline: str, cwd: Path) -> str: cmdline_split = cmdline.split() def postprocess_cmdline(cmdline: str, cwd: Path, exe: str) -> str: # only use line with commandline from the token that includes the exe name # reason again the renderer tests... idx = 0 for elem in cmdline.split(): if exe in elem: idx = cmdline.index(elem) cmdline_split = cmdline[idx:].split() cmdline_proc = [] # change absolute paths into relative ones Loading Loading @@ -151,6 +199,7 @@ def parse_errors_from_sysout( pattern_usan = re.compile(r"(lib_.+|apps)\/(.*\.[ch]):(\d+):(\d+): runtime error:") pattern_msan = re.compile(r" MemorySanitizer: ") pattern_asan = re.compile(r"==\d+==ERROR: .+Sanitizer: ") state = ParserState.OUT accu = [] Loading @@ -163,18 +212,26 @@ def parse_errors_from_sysout( m_usan = re.search(pattern_usan, line) m_msan = re.search(pattern_msan, line) m_asan = re.search(pattern_asan, line) usan_start_found = m_usan is not None msan_start_found = m_msan is not None and not line.startswith("SUMMARY:") asan_start_found = m_asan is not None assert usan_start_found != msan_start_found or ( not usan_start_found and not msan_start_found ) if usan_start_found or msan_start_found: matches_found = sum([usan_start_found, msan_start_found, asan_start_found]) assert matches_found <= 1 if matches_found > 0: assert state == ParserState.OUT state = ParserState.IN accu = [] err_cls = UsanError if m_usan is not None else MsanError err_cls = ( UsanError if m_usan is not None else MsanError if m_msan is not None else AsanError ) if state == ParserState.IN: accu.append(line) Loading Loading
scripts/parse_sanitizer_errors_from_xml_report.py +65 −8 Original line number Diff line number Diff line #!/usr/env python3 from numpy import trace import pandas as pd from xml.etree import ElementTree import argparse Loading Loading @@ -78,6 +79,44 @@ class MsanError(SanitizerError): SUMMARY_ID = "MemorySanitizer" class AsanError(SanitizerError): SUMMARY_ID = "AddressSanitizer" def parse_type_and_location(self, traceback, cwd) -> Tuple[str, str]: first_line = traceback.split("\n")[0].strip() type = "" location = "" if "AddressSanitizer" in first_line: last_line = traceback.split("\n")[-1].strip() assert last_line.startswith(f"SUMMARY: {self.SUMMARY_ID}") m = re.match( r"SUMMARY: " + self.SUMMARY_ID + r": ([a-z-]*) (.*\/.*\.[ch]:\d+:\d+) in", last_line, ) assert m is not None type, location = m.groups() elif "LeakSanitizer" in first_line: type = "memory leaks" # for location, we just pick from the first leak, even if there are more in there # perfect accurac not needed here for line in traceback.split("\n"): # this assumes that number #0 always is the executable itself and has no file associated if line.strip().startswith("#1"): location = line.split()[-1] break else: raise NotImplementedError("Unknown Asan type") if Path(location).is_absolute(): location = str(Path(location).relative_to(cwd)) return type, location def parse_commandlines_from_sysout(sysout: str, cwd: Path) -> dict: commandlines = { "IVAS_cod": "", Loading @@ -92,17 +131,19 @@ def parse_commandlines_from_sysout(sysout: str, cwd: Path) -> dict: # search for name of executable in line # it is repeated in the sanitizer traceback, hence the "not in" part # the "not at the start" condition is for eid-xor (there are also lines like this: "eid-xor command:") # the "does not contain CalledProcessError" is for the renderer tests if ( re.search(exe, line) is not None and " in _start " not in line and not line.strip().startswith(exe) and "CalledProcessError" not in line ): if commandlines[exe] != "": logging.debug( f"Commandline for {exe} already found, skip second one." ) else: commandlines[exe] = postprocess_cmdline(line.strip(), cwd) commandlines[exe] = postprocess_cmdline(line.strip(), cwd, exe) # assumption: only one commandline per line break Loading @@ -110,8 +151,15 @@ def parse_commandlines_from_sysout(sysout: str, cwd: Path) -> dict: return commandlines def postprocess_cmdline(cmdline: str, cwd: Path) -> str: cmdline_split = cmdline.split() def postprocess_cmdline(cmdline: str, cwd: Path, exe: str) -> str: # only use line with commandline from the token that includes the exe name # reason again the renderer tests... idx = 0 for elem in cmdline.split(): if exe in elem: idx = cmdline.index(elem) cmdline_split = cmdline[idx:].split() cmdline_proc = [] # change absolute paths into relative ones Loading Loading @@ -151,6 +199,7 @@ def parse_errors_from_sysout( pattern_usan = re.compile(r"(lib_.+|apps)\/(.*\.[ch]):(\d+):(\d+): runtime error:") pattern_msan = re.compile(r" MemorySanitizer: ") pattern_asan = re.compile(r"==\d+==ERROR: .+Sanitizer: ") state = ParserState.OUT accu = [] Loading @@ -163,18 +212,26 @@ def parse_errors_from_sysout( m_usan = re.search(pattern_usan, line) m_msan = re.search(pattern_msan, line) m_asan = re.search(pattern_asan, line) usan_start_found = m_usan is not None msan_start_found = m_msan is not None and not line.startswith("SUMMARY:") asan_start_found = m_asan is not None assert usan_start_found != msan_start_found or ( not usan_start_found and not msan_start_found ) if usan_start_found or msan_start_found: matches_found = sum([usan_start_found, msan_start_found, asan_start_found]) assert matches_found <= 1 if matches_found > 0: assert state == ParserState.OUT state = ParserState.IN accu = [] err_cls = UsanError if m_usan is not None else MsanError err_cls = ( UsanError if m_usan is not None else MsanError if m_msan is not None else AsanError ) if state == ParserState.IN: accu.append(line) Loading