From 4e4ec115ef44943005371c6cda1d0b71e8c0367c Mon Sep 17 00:00:00 2001 From: manunicholasjacob Date: Fri, 31 Jul 2026 21:29:24 -0500 Subject: [PATCH] fix(probes): guard badchars ASCII selection against max_ascii_variants=1 _select_ascii divided by (limit - 1) after guards that let limit == 1 through, so the user-settable max_ascii_variants=1 raised ZeroDivisionError at probe construction. The sibling _select_positions in the same class already special-cases cap == 1; mirror that. Signed-off-by: manunicholasjacob --- garak/probes/badchars.py | 4 ++++ tests/probes/test_probes_badchars.py | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 tests/probes/test_probes_badchars.py diff --git a/garak/probes/badchars.py b/garak/probes/badchars.py index 664ad5e78..cbb80eca6 100644 --- a/garak/probes/badchars.py +++ b/garak/probes/badchars.py @@ -383,6 +383,10 @@ def _select_positions( def _select_ascii(limit: int) -> List[str]: if limit is None or limit <= 0 or limit >= len(ASCII_PRINTABLE): return list(ASCII_PRINTABLE) + + if limit == 1: + return [ASCII_PRINTABLE[0]] + step = max(1, (len(ASCII_PRINTABLE) - 1) // (limit - 1)) selected = [ASCII_PRINTABLE[i] for i in range(0, len(ASCII_PRINTABLE), step)] return selected[:limit] diff --git a/tests/probes/test_probes_badchars.py b/tests/probes/test_probes_badchars.py new file mode 100644 index 000000000..a6333811c --- /dev/null +++ b/tests/probes/test_probes_badchars.py @@ -0,0 +1,21 @@ +"""Regression tests for the badchars probe ASCII variant cap.""" + +import pytest + +from garak.probes.badchars import ASCII_PRINTABLE, BadCharacters + + +@pytest.mark.parametrize( + ("limit", "expected_count"), + [ + (1, 1), + (2, 2), + (3, 3), + ], +) +def test_select_ascii_respects_small_limits(limit: int, expected_count: int) -> None: + selected = BadCharacters._select_ascii(limit) + + assert len(selected) == expected_count + assert selected[0] == ASCII_PRINTABLE[0] + assert all(character in ASCII_PRINTABLE for character in selected)