def pull_out_adversarial_malware(
        x: np.ndarray,
        y: np.ndarray,
        sample_sizes: np.ndarray,
        initial_dtype: np.dtype,
        input_perturb_sizes: list[list[int]] | None = None,
        input_perturb_starts: list[list[int]] | None = None,
    ) -> (
        tuple[np.ndarray, np.ndarray, np.ndarray]
        | tuple[np.ndarray, np.ndarray, np.ndarray, list[list[int]], list[list[int]]]
    ):
        """
        Fetches the malware from the data

        :param x: Batch of data which will contain a mix of adversarial examples and unperturbed data.
        :param y: Labels indicating which are valid adversarial examples or not.
        :param initial_dtype: Data can be given in a few formats (uin16, float, etc.) so use initial_dtype
                              to make the returned sample match the original.
        :param sample_sizes: Size of the original data files
        :param input_perturb_sizes: List of length batch size, each element is in itself a list containing
                                    the size of the allowable perturbation region
        :param input_perturb_starts: List of length batch size, each element is in itself a list containing
                                     the start of perturbation region.

        :return adv_x: array composed of only the data that we can make valid adversarial examples from.
        :return adv_y: labels, all ones.
        """
        num_of_malware_samples = int(np.sum(y))

        # make array and allocate, much faster than appending to list and converting
        adv_x = np.zeros((num_of_malware_samples, x.shape[1]), dtype=initial_dtype)
        adv_y = np.ones((num_of_malware_samples, 1))

        adv_sample_sizes = np.zeros((num_of_malware_samples,), dtype=int)
        perturb_sizes = []
        perturb_starts = []

        j = 0
        for i, label in enumerate(y):
            if label == 1:
                adv_x[j] = x[i]
                adv_sample_sizes[j] = int(sample_sizes[i])
                j += 1
                if input_perturb_sizes is not None and input_perturb_starts is not None:
                    perturb_sizes.append(input_perturb_sizes[i])
                    perturb_starts.append(input_perturb_starts[i])

        if input_perturb_sizes is not None and input_perturb_starts is not None:
            return adv_x, adv_y, adv_sample_sizes, perturb_starts, perturb_sizes

        return adv_x, adv_y, adv_sample_sizes

        Fetches the malware from the data

        :param x: Batch of data which will contain a mix of adversarial examples and unperturbed data.
        :param y: Labels indicating which are valid adversarial examples or not.
        :param initial_dtype: Data can be given in a few formats (uin16, float, etc.) so use initial_dtype
                              to make the returned sample match the original.
        :param sample_sizes: Size of the original data files
        :param input_perturb_sizes: List of length batch size, each element is in itself a list containing
                                    the size of the allowable perturbation region
        :param input_perturb_starts: List of length batch size, each element is in itself a list containing
                                     the start of perturbation region.

        :return adv_x: array composed of only the data that we can make valid adversarial examples from.
        :return adv_y: labels, all ones.
        
art/attacks/evasion/pe_malware_attack.py