def run_attack(
    x: np.ndarray,
    y: np.ndarray,
    sample_is_robust: np.ndarray,
    attack: EvasionAttack,
    estimator_orig: "CLASSIFIER_TYPE",
    norm: int | float | str = np.inf,
    eps: float = 0.3,
    **kwargs,
) -> tuple[np.ndarray, np.ndarray]:
    """
    Run attack.

    :param x: An array of the original inputs.
    :param y: An array of the labels.
    :param sample_is_robust: Store the initial robustness of examples.
    :param attack: Evasion attack to run.
    :param estimator_orig: Original estimator to be attacked by adversarial examples.
    :param norm: The norm of the adversarial perturbation. Possible values: "inf", np.inf, 1 or 2.
    :param eps: Maximum perturbation that the attacker can introduce.
    :return: An array holding the adversarial examples.
    """
    # Attack only correctly classified samples
    x_robust = x[sample_is_robust]
    y_robust = y[sample_is_robust]

    # Generate adversarial examples
    x_robust_adv = attack.generate(x=x_robust, y=y_robust, **kwargs)
    y_pred_robust_adv = estimator_orig.predict(x_robust_adv)

    # Check and update successful examples
    rel_acc = 1e-4
    order = np.inf if norm == "inf" else norm
    assert isinstance(order, (int, float))
    norm_is_smaller_eps = (1 - rel_acc) * np.linalg.norm(
        (x_robust_adv - x_robust).reshape((x_robust_adv.shape[0], -1)), axis=1, ord=order
    ) <= eps

    if attack.targeted:
        samples_misclassified = np.argmax(y_pred_robust_adv, axis=1) == np.argmax(y_robust, axis=1)
    elif not attack.targeted:
        samples_misclassified = np.argmax(y_pred_robust_adv, axis=1) != np.argmax(y_robust, axis=1)
    else:  # pragma: no cover
        raise ValueError

    sample_is_not_robust = np.logical_and(samples_misclassified, norm_is_smaller_eps)

    x_robust[sample_is_not_robust] = x_robust_adv[sample_is_not_robust]
    x[sample_is_robust] = x_robust

    sample_is_robust[sample_is_robust] = np.invert(sample_is_not_robust)

    return x, sample_is_robust

    Run attack.

    :param x: An array of the original inputs.
    :param y: An array of the labels.
    :param sample_is_robust: Store the initial robustness of examples.
    :param attack: Evasion attack to run.
    :param estimator_orig: Original estimator to be attacked by adversarial examples.
    :param norm: The norm of the adversarial perturbation. Possible values: "inf", np.inf, 1 or 2.
    :param eps: Maximum perturbation that the attacker can introduce.
    :return: An array holding the adversarial examples.
    
art/attacks/evasion/auto_attack.py