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())
Exemple #3
0
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())