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

Code before:
            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:
            # bail if capa encountered file limitation e.g. a packed binary
            # do show the output in verbose mode, though.
            if not (args.verbose or args.vverbose or args.json):
                logger.debug("file limitation short circuit, won't analyze fully.")
                raise ShouldExitError(E_FILE_LIMITATION)
    return found_file_limitation


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

      For example, notifies when handling .NET samples in a sandbox, which may rely on different API patterns.

    raises:
      ShouldExitError: if the program is invoked incorrectly and should exit.
    """
    found_dynamic_limitation = False
    for file_extractor in file_extractors:
        pure_dynamic_capabilities = find_file_capabilities(rules, file_extractor, {})
        found_dynamic_limitation = has_dynamic_limitation(rules, pure_dynamic_capabilities)

    # file limitations that rely on non-file scope won't be detected here.
    # nor on FunctionName features, because pefile doesn't support this.
    if found_dynamic_limitation:
        # bail if capa encountered file limitation e.g. a dotnet sample is detected
        # do show the output in verbose mode, though.
        if not (args.verbose or args.vverbose or args.json):
            logger.debug("file limitation short circuit, won't analyze fully.")
            raise ShouldExitError(E_FILE_LIMITATION)
    return found_dynamic_limitation


def get_signatures_from_cli(args, input_format: str, backend: str) -> list[Path]:
    if backend != BACKEND_VIV:
        logger.debug("skipping library code matching: only supported by the vivisect backend")
        return []

    if input_format != FORMAT_PE:
        logger.debug("skipping library code matching: signatures only supports PE files")
        return []

Review comment (bug):
please put the explanation and notes before the args/returns/raises blocks of the doctstring.

```suggestion
      Does the dynamic analysis describe some trace that we may not support well?
      For example, .NET samples detonated in a sandbox, which may rely on different API patterns than we currently describe in our rules.

    args:
      args: The parsed command line arguments from `install_common_args`.

    raises:
      ShouldExitError: if the program is invoked incorrectly and should exit.
```

Code after:
            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:
            # bail if capa encountered file limitation e.g. a packed binary
            # do show the output in verbose mode, though.
            if not (args.verbose or args.vverbose or args.json):
                logger.debug("file limitation short circuit, won't analyze fully.")
                raise ShouldExitError(E_FILE_LIMITATION)
    return found_file_limitation


def find_dynamic_limitations_from_cli(args, rules: RuleSet, file_extractors: list[FeatureExtractor]) -> bool:
    """
    Does the dynamic analysis describe some trace that we may not support well?
    For example, .NET samples detonated in a sandbox, which may rely on different API patterns than we currently describe in our rules.

    args:
      args: The parsed command line arguments from `install_common_args`.

    raises:
      ShouldExitError: if the program is invoked incorrectly and should exit..
    """
    found_dynamic_limitation = False
    for file_extractor in file_extractors:
        pure_dynamic_capabilities = find_file_capabilities(rules, file_extractor, {})
        found_dynamic_limitation = has_dynamic_limitation(rules, pure_dynamic_capabilities)

    if found_dynamic_limitation:
        # bail if capa encountered file limitation e.g. a dotnet sample is detected
        # do show the output in verbose mode, though.
        if not (args.verbose or args.vverbose or args.json):
            logger.debug("file limitation short circuit, won't analyze fully.")
            raise ShouldExitError(E_FILE_LIMITATION)
    return found_dynamic_limitation


def get_signatures_from_cli(args, input_format: str, backend: str) -> list[Path]:
    if backend != BACKEND_VIV:
        logger.debug("skipping library code matching: only supported by the vivisect backend")
        return []

    if input_format != FORMAT_PE:
        logger.debug("skipping library code matching: signatures only supports PE files")
        return []