Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions garak/probes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,12 @@ def probe(self, generator) -> Iterable[garak.attempt.Attempt]:
prompts = copy.deepcopy(
self.prompts
) # make a copy to avoid mutating source list
if not prompts:
# A probe can have an empty prompt set (e.g. translation empties it);
# the progress bar below tolerates zero but the `prompts[0]` check
# does not. Produce no attempts instead of raising IndexError (#2026).
logging.warning("probe %s has an empty prompt set", self.probename)
return []
preparation_bar = tqdm.tqdm(
total=len(prompts),
leave=False,
Expand Down
19 changes: 18 additions & 1 deletion tests/probes/test_probes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import langcodes
import pytest
import re
from unittest.mock import MagicMock

from garak import _config, _plugins
from garak.attempt import Turn, Conversation, Message, Attempt
Expand Down Expand Up @@ -223,6 +224,23 @@ def test_mint_attempt(prompt):
assert attempt.prompt.last_message().text == "test example"


def test_probe_with_empty_prompts_returns_no_attempts():
"""An empty (or translation-emptied) prompt set must not IndexError.

Regression test for #2026: ``probe()`` indexed ``prompts[0]`` before
checking the list was non-empty, so a probe whose prompt set came back empty
raised ``IndexError`` instead of producing no attempts.
"""
import garak.probes.base

probe = garak.probes.base.Probe()
probe.prompts = []

attempts = probe.probe(MagicMock())

assert attempts == []


@pytest.mark.parametrize("prompt", PROMPT_EXAMPLES)
def test_mint_attempt_with_run_system_prompt(prompt):
import garak.probes.base
Expand Down Expand Up @@ -361,4 +379,3 @@ def test_encoding_probe_attempt_carries_payload_intent(loaded_intent_service):
attempt.intent == expected_intent
), "attempt intent must reflect the payload-specific intent set in _attempt_prestore_hook"