A long-path self-test aborted or passed depending on the length of $TMPDIR - #1411
A long-path self-test aborted or passed depending on the length of $TMPDIR#1411xroche wants to merge 5 commits into
Conversation
st_direnum and st_cookieimport built their directory by appending fixed-size segments while a counter stayed under 300, then asserted the result had exceeded MAX_PATH. The starting length is the base directory's, so the final value lands somewhere different for every $TMPDIR, and for a band of lengths it lands on exactly 260, where the assertion aborts. It read as an intermittent CI abort. Fold the four copies of that loop into st_mkdeep(), which stops on the MAX_PATH comparison itself. Both tests now sweep a full segment's worth of base-dir lengths. Closes #1409 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Xavier Roche <roche@httrack.com>
Review caught the first version deleting assertf(dirlen > 260) from st_direnum and st_cookieimport on the grounds that st_mkdeep now guarantees it. That assertion was the only thing pinning that the path ever exceeded MAX_PATH: with it gone, reverting the loop to the old arithmetic bound reintroduces #1409 and the whole suite stays green. Assert the postcondition inside st_mkdeep and keep it at the two call sites, where it also catches a helper returning the base length rather than the deep one. Both mutants now go red. Charge the non-ASCII segment by code point while here: Windows measures MAX_PATH in UTF-16 units, so a byte-only bound can exit at 261 bytes and 259 units, under the limit these tests exist to cross. Reuse repeat_chars for the padding, and fail the sweep if it queues nothing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Xavier Roche <roche@httrack.com>
st_mkdeep charged its slack only against the non-ASCII segment it appends, so a base directory that is itself non-ASCII made the byte count overstate the length Windows measures MAX_PATH in, and the loop stopped short of the limit. With a 30-é base, direnum built a 264-byte directory that is 231 UTF-16 units: #1409's bug moved from the length axis to the charset axis. The loop and the guarantee it asserts now go through st_utf16_units(), which counts the whole buffer and charges a non-BMP code point the two units its surrogate pair costs. A byte it cannot read is charged short, which only ever builds a longer path. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Xavier Roche <roche@httrack.com>
The sweep ran on mktemp -d, which is ASCII, so no mutant of st_mkdeep's slack arithmetic could red it: the base now carries 15 é ahead of the ASCII pad, which is what makes the charset axis observable at all. longpath-io and mirror-io join the sweep too — they had lost their own stop bound and gained no replacement, so restoring the old arithmetic one left both green while the other two failed. The sweep helper takes a mode, and direnum asserts a head that says something (two leaves enumerated) rather than a tail that only pins ": OK". What actually detects #1409 is st_mkdeep's assertf, and the helper now says so. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Xavier Roche <roche@httrack.com>
Three probes passed -O "$(mktemp -d)" inline, so nothing held the name and nothing removed it. One trapped directory serves all three; none of them crawls. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Xavier Roche <roche@httrack.com>
|
Follow-up commits address the review P0: The loop and the guarantee it asserts now go through The sweep base is non-ASCII now as well: on Full suite green here: 383 total, 370 pass, 13 skip, 0 fail. |
Four long-path self-tests built their directory by appending fixed-size segments while a counter stayed under 300, then asserted the result had passed MAX_PATH. The starting length is the base directory's, so the final value lands somewhere different for every
$TMPDIR, and for a band of lengths it lands on exactly 260, where the> 260assertion aborts. Two of the four asserted on the directory alone, so they could fire; the other two had a leaf name's worth of slack and never did. It reads as an intermittent CI abort because where a machine's build tree happens to live is what decides whether it trips.The four copies are now one helper that loops on the MAX_PATH comparison itself, so no base length can leave it short. Both tests sweep 41 consecutive base-dir lengths, one segment's worth, so every residue is covered whatever
$TMPDIRis. The pre-fix engine aborts at two of the 41 and the fixed one at none, standalone and throughmake check.The sweep on its own would not have caught a regression. The assertion it replaced was the only thing pinning that the path ever exceeded MAX_PATH, so reverting the loop with that assertion gone reintroduces the bug and the suite stays green. The postcondition is now asserted inside the helper and kept at both call sites, and both mutants go red.
One thing found while in here: the bound was in bytes, but Windows measures MAX_PATH in UTF-16 units, so the 5-byte, 2-unit non-ASCII segment let an exit at 261 bytes be 259 units, under the limit these tests exist to cross. The helper now charges that segment by code point. That part has no local red test, since only the Windows path can observe it.
Closes #1409