From aaf7481bfa09446b78f0722aec74ed1c5fe96d15 Mon Sep 17 00:00:00 2001 From: Szymon Chmal Date: Wed, 9 Sep 2026 22:44:52 -0500 Subject: [PATCH 1/2] =?UTF-8?q?test:=20reproduce=20#141=20=E2=80=94=20a=20?= =?UTF-8?q?tracked=20file=20contains=20a=20raw=20NUL=20byte?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/source-hygiene.test.ts | 60 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/source-hygiene.test.ts diff --git a/src/source-hygiene.test.ts b/src/source-hygiene.test.ts new file mode 100644 index 0000000..d41e8f9 --- /dev/null +++ b/src/source-hygiene.test.ts @@ -0,0 +1,60 @@ +import { execFileSync } from "node:child_process"; +import { readFileSync, statSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; + +import { describe, expect, it } from "vitest"; + +const REPO_ROOT = join(dirname(fileURLToPath(import.meta.url)), ".."); + +const NUL = 0x00; + +/** + * A raw NUL byte in a text file makes `grep` and `ripgrep` classify the whole file as + * binary and print `binary file matches` instead of the matching lines -- so the file + * stops being searchable for every human and agent working in this repo. The byte is + * almost always a `"\0"` escape that was written as the literal character instead. + * + * Enumerated from `git ls-files` rather than a directory walk so the check sees every + * tracked file in the repository (testing rule 4), not just the directories this test + * happened to name. Untracked and ignored files are out of scope: they are not part of + * what anyone clones or searches. + */ +describe("tracked files", () => { + const trackedFiles = execFileSync("git", ["ls-files", "-z"], { + cwd: REPO_ROOT, + encoding: "buffer", + maxBuffer: 32 * 1024 * 1024, + }) + .toString("utf8") + .split("\0") + .filter((name) => name.length > 0) + // A submodule or a path deleted from the working tree is still listed by + // `git ls-files`; only regular files can be read. + .filter((name) => { + try { + return statSync(join(REPO_ROOT, name)).isFile(); + } catch { + return false; + } + }); + + it("were enumerated from the git index", () => { + // Without this, an `execFileSync` that returned nothing would leave `it.each` with an + // empty list and the suite would pass while checking no file at all. + expect(trackedFiles.length).toBeGreaterThan(100); + }); + + it("contain no raw NUL byte, so grep and ripgrep can search them", () => { + const offenders = trackedFiles + .map((name) => ({ name, contents: readFileSync(join(REPO_ROOT, name)) })) + .filter(({ contents }) => contents.includes(NUL)) + .map(({ name, contents }) => { + const offset = contents.indexOf(NUL); + const line = contents.subarray(0, offset).toString("utf8").split("\n").length; + return `${name}:${line} (byte ${offset})`; + }); + + expect(offenders).toEqual([]); + }); +}); From c50221a4ecc207ef3b93b1cad8c0ef9aabe69aff Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 10 Sep 2026 12:43:19 +0000 Subject: [PATCH 2/2] fix(ios): write the download-lock separator as \0 instead of a raw NUL byte The literal NUL in the source made grep and ripgrep classify the whole 2011-line iOS driver as binary, so the file was invisible to a normal search. The escape produces the same runtime string. Closes #141 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_018HHP7Th9NqWfhexmp4V9Pf --- src/drivers/ios/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/ios/index.ts b/src/drivers/ios/index.ts index c77a208..85023d7 100644 --- a/src/drivers/ios/index.ts +++ b/src/drivers/ios/index.ts @@ -591,7 +591,7 @@ export class IosSimctlDriver implements Driver { args: readonly string[], requesterId: string | undefined, ): Promise { - const key = args.join(""); + const key = args.join("\0"); const inFlight = this.#downloadLocks.get(key); if (inFlight !== undefined) { return inFlight;