fix(parsers): validate Windows FFmpeg discovery candidates - #2871
Conversation
5805019 to
4c3ec29
Compare
vanceingalls
left a comment
There was a problem hiding this comment.
Verdict: APPROVE — grade A — rubric CORRECT (on stated scope)
Root-cause fit: Fix is a targeted safety net, not an encoding repair. where.exe's codepage bytes still get decoded as UTF-8 at ffBinaries.ts:112 (unchanged), but the new guard at ffBinaries.ts:111-112 rejects the resulting mojibake candidate via existsSync/accessSync and falls through to scanPath() — which reads process.env.PATH via Node's UTF-16 env APIs, so it's clean. Honest with its PR body ("even when a valid FFmpeg is available through PATH") — does not attempt to recover ffmpeg installed in a cyrillic-only dir absent from PATH.
Claims verified (each with file:line at HEAD):
- "Check that an auto-discovered candidate exists and is executable" —
ffBinaries.ts:111wrapschooseBestPathCandidateinisExecutablePathCandidate(usesexistsSyncon win32 at line 41,accessSync X_OKelsewhere at line 43). - "Fall back to the existing PATH scan when validation fails" —
ffBinaries.ts:112candidate && isExecutablePathCandidate(candidate) ? candidate : scanPath(name). - "Preserve valid Windows
.exeselection and explicit path overrides" —chooseBestPathCandidateuntouched (lines 27-40); env-override branch untouched (lines 138-142). - "Add coverage for corrupted Windows discovery output" — new test at
ffBinaries.test.ts:73-99mocks mojibakewhereoutput + a/valid-tools/ffmpeg.exefallback and asserts PATH fallback. - File-list/diff: 2 files, 36/0 + 2/1 = +38/-1.
Adversarial findings:
- P2 — Doesn't recover ffmpeg in cyrillic/Chinese install paths absent from PATH: still
encoding: "utf-8"atffBinaries.ts:112; noiconv-lite/chcp/ codepage-aware decode. Ticket-body language is broader than this PR delivers; expect a follow-up. - P2 — Only the single "best" candidate is validated:
chooseBestPathCandidatereturns one path; if a mojibake candidate wins the.exepreference but a clean second-line candidate exists inwhere's output, the clean one is discarded before validation. Low practical risk on Windows. - nit — Silent fallback on rejected candidate: no log/warn distinguishes "where errored" from "where succeeded but returned a phantom path".
- nit — Test at
ffBinaries.test.ts:96assertsencoding: "utf-8"in theexecFileSynccall, locking in current lossy decode. Must move if a follow-up switches to codepage-aware decoding. - Standards checklist: no new empty catches, no disabled tests, no TODOs, no oxlint breach.
CI state: All required checks green including Tests on windows-latest (12m45s) and Render on windows-latest (8m13s). MERGEABLE.
Suggested next step: Merge — the fix is minimal, correct for its stated scope, tested on Windows CI, and strictly reduces failure modes. Open a follow-up ticket to actually recover non-ASCII paths (spawn where with encoding: "buffer" and decode via iconv-lite using the active codepage from chcp, or scan the registry/Program Files directly). Verify separately whether APPS-984's reporter expects the cyrillic-recovery case; if so, keep the ticket open.
— Review by Via
james-russo-rames-d-jusso
left a comment
There was a problem hiding this comment.
Reviewed at 4c3ec29a.
Clean fix. isExecutablePathCandidate gates the where/which output before returning, so a mojibake .exe path decoded from Windows CP output can no longer reach process launch when a valid FFmpeg is on PATH. Windows check is existsSync only (correct — no X_OK model on NTFS); Unix uses accessSync(candidate, X_OK) in a try/catch. Regression test asserts the fallback to scanPath when the decoded candidate doesn't exist, and the existing .exe > .cmd selection still passes because both the .exe mock and existsSync mock agree on the same path. LGTM from my side.
Observations
- If
wherereturns multiple candidates and only the highest-priority one is corrupt, the fix drops the entirewherelist and re-scansPATHfrom scratch — a valid.cmdin thewhereoutput is discarded even when it would resolve. In practicescanPathre-derives the same valid path fromPATHenv (which Node reads UTF-8-clean), so this is defensible; documenting the "on validation miss, we prefer PATH scan over iterating remainingwherecandidates" choice in the comment would help future maintainers. - The corrupted-output test uses
/valid-toolsunder mockedprocess.platform="win32". Not a bug —path.delimiteron win32 with a single-entry PATH still resolves — but a real Windows-shaped path (C:\\valid-tools) matches the failure geometry better. Cosmetic.
Nits
Object.defineProperty(process, "platform", { value: "win32", configurable: true })pollutes global state across the whole test file. Existing tests already do this, but a fixture that stashes the original and restores inafterEachwould prevent surprise ordering hazards if someone later reshuffles the describe blocks.
What I didn't verify
- Cache-poisoning safety:
pathLookupCacheis module-scoped and populated with the resolved path on first success. If the first call happens with a corruptedwhereoutput that falls back to a validscanPathresult, that valid result gets cached — good. But if the first call happens whilePATHis unset andwherealso fails,undefinedis cached and all future calls in the process return undefined even after PATH is set. Pre-existing behavior, not touched by this PR — worth flagging separately if it hasn't been.
— Review by Rames D Jusso
fixes reported:1785304892.118879:unicode-home-ffmpeg-discovery; PR #2859 remains unmodified.
4c3ec29 to
59df9d5
Compare
|
Review follow-up at exact head
Verification: focused parser suite 8/8, parser typecheck, changed-file lint/format, diff check, and commit hooks. |
…m#2871) * fix(parsers): validate ffmpeg discovery candidates fixes reported:1785304892.118879:unicode-home-ffmpeg-discovery; PR heygen-com#2859 remains unmodified. * fix(parsers): avoid Windows console path decoding
What
Discover Windows FFmpeg and FFprobe binaries from native current-directory and PATH strings instead of decoding
where.execonsole output.Why
where.exewrites bytes in the active Windows console code page. Decoding that output as UTF-8 can corrupt non-ASCII paths and pass a nonexistent mojibake path into process launch.How
.exeover command shims.whichplus executable validation on Unix and explicit path overrides on every platform.Test plan
.exepreference regression