Repository: mandiant/capa
File: capa/main.py (Python)

Code before:
    except (ELFError, OverflowError) as e:
        logger.error("Input file '%s' is not a valid ELF file: %s", args.input_file, str(e))
        raise ShouldExitError(E_CORRUPT_FILE) from e
    except UnsupportedFormatError as e:
        if input_format == FORMAT_CAPE:
            log_unsupported_cape_report_error(str(e))
        elif input_format == FORMAT_DRAKVUF:
            log_unsupported_drakvuf_report_error(str(e))
        elif input_format == FORMAT_VMRAY:
            log_unsupported_vmray_report_error(str(e))
        else:
            log_unsupported_format_error()
        raise ShouldExitError(E_INVALID_FILE_TYPE) from e
    except EmptyReportError as e:
        if input_format == FORMAT_CAPE:
            log_empty_sandbox_report_error(str(e), sandbox_name="CAPE")
            raise ShouldExitError(E_EMPTY_REPORT) from e
        elif input_format == FORMAT_DRAKVUF:
            log_empty_sandbox_report_error(str(e), sandbox_name="DRAKVUF")
            raise ShouldExitError(E_EMPTY_REPORT) from e
        else:
            log_unsupported_format_error()
            raise ShouldExitError(E_INVALID_FILE_TYPE) from e


def find_static_limitations_from_cli(args, rules: RuleSet, file_extractors: list[FeatureExtractor]) -> bool:
    """
    args:
      args: The parsed command line arguments from `install_common_args`.

    Dynamic feature extractors can handle packed samples and do not need to be considered here.

    raises:
      ShouldExitError: if the program is invoked incorrectly and should exit.
    """
    found_file_limitation = False
    for file_extractor in file_extractors:
        try:
            pure_file_capabilities, _ = find_file_capabilities(rules, file_extractor, {})
            # logger.info("file capabilities: ", pure_file_capabilities)
        except PEFormatError as e:
            logger.error("Input file '%s' is not a valid PE file: %s", args.input_file, str(e))
            raise ShouldExitError(E_CORRUPT_FILE) from e
        except (ELFError, OverflowError) as e:
            logger.error("Input file '%s' is not a valid ELF file: %s", args.input_file, str(e))
            raise ShouldExitError(E_CORRUPT_FILE) from e

        # file limitations that rely on non-file scope won't be detected here.
        # nor on FunctionName features, because pefile doesn't support this.
        found_file_limitation = has_static_limitation(rules, pure_file_capabilities)
        if found_file_limitation:

Review comment (refactor):
one thing we're losing in the changes is the documentation/naming that makes clear that the static limitations are derived from *file* extractors (like pefile) not full disassembly-derived extractors (like vivisect). they should be lightweight. so lets find the right place to re-add this documentation.

Code after:
    except (ELFError, OverflowError) as e:
        logger.error("Input file '%s' is not a valid ELF file: %s", args.input_file, str(e))
        raise ShouldExitError(E_CORRUPT_FILE) from e
    except UnsupportedFormatError as e:
        if input_format == FORMAT_CAPE:
            log_unsupported_cape_report_error(str(e))
        elif input_format == FORMAT_DRAKVUF:
            log_unsupported_drakvuf_report_error(str(e))
        elif input_format == FORMAT_VMRAY:
            log_unsupported_vmray_report_error(str(e))
        else:
            log_unsupported_format_error()
        raise ShouldExitError(E_INVALID_FILE_TYPE) from e
    except EmptyReportError as e:
        if input_format == FORMAT_CAPE:
            log_empty_sandbox_report_error(str(e), sandbox_name="CAPE")
            raise ShouldExitError(E_EMPTY_REPORT) from e
        elif input_format == FORMAT_DRAKVUF:
            log_empty_sandbox_report_error(str(e), sandbox_name="DRAKVUF")
            raise ShouldExitError(E_EMPTY_REPORT) from e
        else:
            log_unsupported_format_error()
            raise ShouldExitError(E_INVALID_FILE_TYPE) from e


def find_static_limitations_from_cli(args, rules: RuleSet, file_extractors: list[FeatureExtractor]) -> bool:
    """
    args:
      args: The parsed command line arguments from `install_common_args`.

    Only file-scoped feature extractors like pefile are used.
    Dynamic feature extractors can handle packed samples and do not need to be considered here.

    raises:
      ShouldExitError: if the program is invoked incorrectly and should exit.
    """
    found_file_limitation = False
    for file_extractor in file_extractors:
        try:
            pure_file_capabilities = find_file_capabilities(rules, file_extractor, {})
        except PEFormatError as e:
            logger.error("Input file '%s' is not a valid PE file: %s", args.input_file, str(e))
            raise ShouldExitError(E_CORRUPT_FILE) from e
        except (ELFError, OverflowError) as e:
            logger.error("Input file '%s' is not a valid ELF file: %s", args.input_file, str(e))
            raise ShouldExitError(E_CORRUPT_FILE) from e

        # file limitations that rely on non-file scope won't be detected here.
        # nor on FunctionName features, because pefile doesn't support this.
        found_file_limitation = has_static_limitation(rules, pure_file_capabilities)
        if found_file_limitation: