Skip to content

Commit d0e1010

Browse files
Decide the confinement fuzz by the oracles, not by whether it reverted
Both confinement tests swallowed every revert, so which side of the domain a pair was on was decided by the library's own answer. A pair both oracles accept now has to produce a path, and the neighbourhood test asserts the agreement it was already named for: a range that opens or closes one byte too far disagrees with the spelled-out alphabet instead of handing back a path that still happens to be confined. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 116717f commit d0e1010

1 file changed

Lines changed: 30 additions & 9 deletions

File tree

test/src/lib/LibFs.pathForTaggedContract.t.sol

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,11 @@ contract LibFsPathForTaggedContractTest is Test {
166166
/// `GENERATED_DIR`. Each argument is either arbitrary bytes or built from its
167167
/// alphabet, chosen by the fuzzer, so the rejected domain is reached by the
168168
/// raw branches and the accepted domain — which arbitrary bytes essentially
169-
/// never reach — by the constructed ones. Nothing is assumed away: a pair
170-
/// that reverts proves confinement by producing no path at all.
169+
/// never reach — by the constructed ones. Nothing is assumed away: every
170+
/// pair reaches an assertion, because which side of the domain it is on is
171+
/// decided by the oracles rather than by whether the call reverted. A pair
172+
/// both oracles accept must produce a confined path, and a revert is a
173+
/// claim that at least one of them rejects it.
171174
function testPathForTaggedContractAcceptedArgumentsAreConfined(
172175
bytes memory tagSeed,
173176
bytes memory nameSeed,
@@ -180,13 +183,22 @@ contract LibFsPathForTaggedContractTest is Test {
180183
assertTrue(LibCodeGenSlow.isTagSlow(tag), "a tag outside the alphabet was accepted");
181184
assertTrue(LibCodeGenSlow.isIdentifierSlow(contractName), "a name outside the alphabet was accepted");
182185
assertConfined(path);
183-
} catch {}
186+
} catch {
187+
assertFalse(
188+
LibCodeGenSlow.isTagSlow(tag) && LibCodeGenSlow.isIdentifierSlow(contractName),
189+
"a pair both oracles accept produced no path"
190+
);
191+
}
184192
}
185193

186-
/// The same confinement, stated over a pair that is an accepted tag and an
187-
/// accepted name with one byte of one of them replaced by an arbitrary one.
188-
/// This is the neighbourhood of the accepted domain, which uniform fuzzing
189-
/// never reaches, and it is where an off by one in either check would show.
194+
/// The same confinement and the same agreement with the oracles, stated over
195+
/// a pair that is an accepted tag and an accepted name with one byte of one
196+
/// of them replaced by an arbitrary one. This is the neighbourhood of the
197+
/// accepted domain, which uniform fuzzing never reaches, and it is where an
198+
/// off by one in either check shows: such a byte is admitted or refused by
199+
/// the library against an oracle that spells its alphabet out, so a range
200+
/// that opens or closes one too far disagrees here rather than producing a
201+
/// path that still happens to be confined.
190202
function testPathForTaggedContractOneBadByteIsConfined(
191203
bytes memory tagSeed,
192204
bytes memory nameSeed,
@@ -201,9 +213,18 @@ contract LibFsPathForTaggedContractTest is Test {
201213
} else {
202214
nameBytes[position % nameBytes.length] = bytes1(badByte);
203215
}
204-
try iExternal.pathForTaggedContract(string(tagBytes), string(nameBytes)) returns (string memory path) {
216+
string memory tag = string(tagBytes);
217+
string memory contractName = string(nameBytes);
218+
try iExternal.pathForTaggedContract(tag, contractName) returns (string memory path) {
219+
assertTrue(LibCodeGenSlow.isTagSlow(tag), "a tag outside the alphabet was accepted");
220+
assertTrue(LibCodeGenSlow.isIdentifierSlow(contractName), "a name outside the alphabet was accepted");
205221
assertConfined(path);
206-
} catch {}
222+
} catch {
223+
assertFalse(
224+
LibCodeGenSlow.isTagSlow(tag) && LibCodeGenSlow.isIdentifierSlow(contractName),
225+
"a pair both oracles accept produced no path"
226+
);
227+
}
207228
}
208229

209230
/// No path is produced for the tag at all, and the error names the tag

0 commit comments

Comments
 (0)