def find_redos(pattern: str, flags: int, output: TextOutput, parser): try: parsed = parser(pattern, flags) except Exception as e: print(f"Error parsing: {pattern}", e) return output.next() for redos in find(parsed): if redos.starriness > 2: output.record(redos, pattern) yield redos
def handle_file(filename: str, output: TextOutput): with open(filename, "rb") as f: code = f.read() for regex in find_regexes(code): pattern = regex.pattern if len(pattern) < 5: continue # (.+)+ if pattern.count("*") + pattern.count("+") + pattern.count(",}") < 2: continue # no ReDoS possible try: logging.debug("%s#%s: %s", filename, regex.lineno, pattern) parsed = SreOpParser().parse_sre(pattern, regex.flags) except: try: fixed = fix_js_regex(pattern) re.compile(fixed, regex.flags) except: if regex.definitely_regex: print( f"Error parsing: {pattern} from {filename} line {regex.lineno}\n" ) continue try: parsed = SreOpParser().parse_sre(fixed, regex.flags) except: print( f"Error in regexploit parsing: {pattern} from {filename}") print(traceback.format_exc()) continue try: output.next() for redos in find(parsed): if redos.starriness > 2: context = None try: context = code.splitlines()[regex.lineno - 1].decode().strip() except UnicodeDecodeError: pass output.record( redos, pattern, filename=filename, lineno=regex.lineno, context=context, ) except Exception: print( f"Error finding ReDoS: {pattern} from {filename} #{regex.lineno}" ) print(traceback.format_exc())
def handle_file(filename: str, output: TextOutput): with open(filename, "rb") as f: code = f.read() try: code_ast = ast.parse(code) pnv = PythonNodeVisitor() pnv.visit(code_ast) except RecursionError: print(f"RecursionError parsing AST for {filename}") return except SyntaxError as e: print(f"Bad Python3 syntax in {filename}: {e}") return for regex in pnv.patterns: try: parsed = SreOpParser().parse_sre(regex.pattern, regex.flags) except re.error: continue # We will have many strings which aren't actually regexes try: output.next() for redos in find(parsed): if redos.starriness > 2: context = None try: context = code.splitlines()[regex.lineno - 1].decode().strip() except UnicodeDecodeError: pass output.record( redos, regex.pattern, filename=filename, lineno=regex.lineno, context=context, ) except Exception: print( f"Error finding ReDoS: {regex.pattern} from {filename} #{regex.lineno}" ) print(traceback.format_exc())