From ed25c570941e2265d00c99d0818c47fe209addf4 Mon Sep 17 00:00:00 2001 From: Matistjati Date: Tue, 19 Aug 2025 21:23:28 +0200 Subject: [PATCH 1/4] Make input validator fuzzing deterministic --- problemtools/verifyproblem.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/problemtools/verifyproblem.py b/problemtools/verifyproblem.py index 8b7b72df..56d5f699 100644 --- a/problemtools/verifyproblem.py +++ b/problemtools/verifyproblem.py @@ -954,13 +954,14 @@ def __str__(self) -> str: # Junk data. The validator should reject these cases +rng = random.Random(42) _JUNK_CASES = [ ('an empty file', b''), - ('a binary file with random bytes', bytearray(random.Random(0).randbytes(1024))), + ('a binary file with random bytes', bytearray(random.Random(42).randbytes(1024))), ('a text file with the ASCII characters 32 up to 127', bytearray(x for x in range(32, 127))), ( 'a random text file with printable ASCII characters', - bytearray(random.choice(string.printable.encode('utf8')) for _ in range(200)), + bytearray(rng.choice(string.printable.encode('utf8')) for _ in range(200)), ), ] @@ -992,18 +993,17 @@ def _build_junk_modifier( return (desc, p.search, lambda text: p.sub(repl, text)) +rng = random.Random(42) _JUNK_MODIFICATIONS = [ - _build_junk_modifier( - 'spaces added where there already is whitespace', r'\s', lambda m: m.group(0) + ' ' * random.randint(1, 5) - ), - _build_junk_modifier('spaces added to the end of a line', r'\n', lambda m: m.group(0) + ' ' * random.randint(1, 5)), - _build_junk_modifier('newlines added where there already are newlines', '\n', lambda m: '\n' * random.randint(2, 5)), + _build_junk_modifier('space added where there already is whitespace', r'\s', lambda m: m.group(0) + ' '), + _build_junk_modifier('space added to the end of a line', r'\n', lambda m: m.group(0) + ' '), + _build_junk_modifier('newlines added where there already are newlines', '\n', lambda m: '\n\n'), _build_junk_modifier('leading zeros added to integers', r'(^|[^.]\b)([0-9]+)\b', r'\g<1>0000000000\g<2>'), _build_junk_modifier('trailing zeros added to real number decimal portion', r'\.[0-9]+\b', r'\g<0>0000000000'), ( 'random junk added to the end of the file', lambda f: True, - lambda f: f + ''.join(random.choice(string.printable) for _ in range(200)), + lambda f: f + ''.join(rng.choice(string.printable) for _ in range(200)), ), ] From 0e39aa53caeaa0c37f259ed51c75287bfd289d6c Mon Sep 17 00:00:00 2001 From: Matistjati Date: Wed, 20 Aug 2025 13:57:49 +0200 Subject: [PATCH 2/4] Make RNG usage fully scoped --- problemtools/verifyproblem.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/problemtools/verifyproblem.py b/problemtools/verifyproblem.py index cc167915..c39f82c5 100644 --- a/problemtools/verifyproblem.py +++ b/problemtools/verifyproblem.py @@ -954,14 +954,13 @@ def __str__(self) -> str: # Junk data. The validator should reject these cases -rng = random.Random(42) _JUNK_CASES = [ ('an empty file', b''), ('a binary file with random bytes', bytearray(random.Random(42).randbytes(1024))), ('a text file with the ASCII characters 32 up to 127', bytearray(x for x in range(32, 127))), ( 'a random text file with printable ASCII characters', - bytearray(rng.choice(string.printable.encode('utf8')) for _ in range(200)), + (lambda rng=random.Random(42): bytearray(rng.choice(string.printable.encode()) for _ in range(200)))(), ), ] @@ -997,7 +996,6 @@ def _build_junk_modifier( return (desc, p.search, lambda text: p.sub(repl, text)) -rng = random.Random(42) _JUNK_MODIFICATIONS = [ _build_junk_modifier('space added where there already is whitespace', r'\s', lambda m: m.group(0) + ' '), _build_junk_modifier('space added to the end of a line', r'\n', lambda m: m.group(0) + ' '), @@ -1007,7 +1005,7 @@ def _build_junk_modifier( ( 'random junk added to the end of the file', lambda f: True, - lambda f: f + ''.join(rng.choice(string.printable) for _ in range(200)), + lambda f: (lambda rng=random.Random(42): f + ''.join(rng.choice(string.printable) for _ in range(200)))(), ), ] From 5cfac906dcbab4b73ae747070306c5f0556dd51a Mon Sep 17 00:00:00 2001 From: Matistjati Date: Wed, 20 Aug 2025 13:59:46 +0200 Subject: [PATCH 3/4] Add back utf-8 explicitly --- problemtools/verifyproblem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problemtools/verifyproblem.py b/problemtools/verifyproblem.py index c39f82c5..47df9dbc 100644 --- a/problemtools/verifyproblem.py +++ b/problemtools/verifyproblem.py @@ -960,7 +960,7 @@ def __str__(self) -> str: ('a text file with the ASCII characters 32 up to 127', bytearray(x for x in range(32, 127))), ( 'a random text file with printable ASCII characters', - (lambda rng=random.Random(42): bytearray(rng.choice(string.printable.encode()) for _ in range(200)))(), + (lambda rng=random.Random(42): bytearray(rng.choice(string.printable.encode('utf8')) for _ in range(200)))(), ), ] From 81e9f2b92974c0cf39395e8cf3f383dc0ce56ac4 Mon Sep 17 00:00:00 2001 From: Matistjati Date: Wed, 20 Aug 2025 14:05:07 +0200 Subject: [PATCH 4/4] Fix mypy error --- problemtools/verifyproblem.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/problemtools/verifyproblem.py b/problemtools/verifyproblem.py index 47df9dbc..78398459 100644 --- a/problemtools/verifyproblem.py +++ b/problemtools/verifyproblem.py @@ -960,7 +960,7 @@ def __str__(self) -> str: ('a text file with the ASCII characters 32 up to 127', bytearray(x for x in range(32, 127))), ( 'a random text file with printable ASCII characters', - (lambda rng=random.Random(42): bytearray(rng.choice(string.printable.encode('utf8')) for _ in range(200)))(), + (lambda rng: bytearray(rng.choice(string.printable.encode('utf8')) for _ in range(200)))(random.Random(42)), ), ] @@ -1005,7 +1005,7 @@ def _build_junk_modifier( ( 'random junk added to the end of the file', lambda f: True, - lambda f: (lambda rng=random.Random(42): f + ''.join(rng.choice(string.printable) for _ in range(200)))(), + lambda f: (lambda rng: f + ''.join(rng.choice(string.printable) for _ in range(200)))(random.Random(42)), ), ]