Skip to content

fix(batch): index the name template by character - #243

Merged
LeadcodeDev merged 1 commit into
chantier/audit-2026-09from
fix/batch-template-unicode
Sep 22, 2026
Merged

LeadcodeDev merged 1 commit into
chantier/audit-2026-09from
fix/batch-template-unicode

Conversation

@LeadcodeDev

Copy link
Copy Markdown
Owner

Severity Low, category correctness. Location: crates/rustmotion/src/cli/commands/batch.rs:74

Impact

resolve_name_template walks the template as raw bytes and casts each one to char, which in Rust is a Latin-1 reinterpretation of the byte value. Substituted {field} values are fine (they go through push_str at line 71); the literal text around them is not. I confirmed the behaviour by compiling the same loop standalone: résumé-{id}.mp4 yields résumé-VAL.mp4 and 动画-{id}.mp4 yields å¨ç»-VAL.mp4. So rustmotion batch --name-template "résumé-{id}.mp4" writes files literally named résumé-abc.mp4 to disk, and the same corruption lands in the [ok] <path> progress lines and in every failure message (item N: ...). A localisation batch — the exact use case {lang}/{id}.mp4 in the module doc is built for — is where a non-ASCII template is most likely. None of the five tests in name_template_tests (lines 448-495) uses a non-ASCII template.

Fix

Iterate template.char_indices() instead of the byte array, pushing the char itself and advancing by c.len_utf8(); the {/} scanning already works on byte offsets that are guaranteed char boundaries, so only the else-arm changes. Add a test asserting resolve_name_template("résumé-{id}.mp4", ...) round-trips the accents.

Evidence the audit read

} else {
            out.push(bytes[cursor] as char);
            cursor += 1;
        }

Stacked on fix/watch-cache-invalidation, which carries the previous finding of this workstream. GitHub shows only this finding's diff; merge in order.

Part of the September 2026 audit remediation chantier. Refs #220 (RM-30).

@LeadcodeDev LeadcodeDev added the bug Something isn't working label Sep 21, 2026
@LeadcodeDev LeadcodeDev self-assigned this Sep 21, 2026
@LeadcodeDev
LeadcodeDev force-pushed the fix/watch-cache-invalidation branch from 408d3e4 to a7a75fa Compare September 22, 2026 06:10
@LeadcodeDev
LeadcodeDev force-pushed the fix/batch-template-unicode branch from 4c04f06 to 8d6a272 Compare September 22, 2026 06:10
@LeadcodeDev
LeadcodeDev force-pushed the fix/watch-cache-invalidation branch from a7a75fa to 581d1ad Compare September 22, 2026 08:34
@LeadcodeDev
LeadcodeDev force-pushed the fix/batch-template-unicode branch from 8d6a272 to 3d27c42 Compare September 22, 2026 08:34
@LeadcodeDev
LeadcodeDev force-pushed the fix/watch-cache-invalidation branch from 581d1ad to b02296e Compare September 22, 2026 08:44
@LeadcodeDev
LeadcodeDev force-pushed the fix/batch-template-unicode branch from 3d27c42 to 87baa16 Compare September 22, 2026 08:44
@LeadcodeDev
LeadcodeDev changed the base branch from fix/watch-cache-invalidation to chantier/audit-2026-09 September 22, 2026 08:53
@LeadcodeDev
LeadcodeDev force-pushed the fix/batch-template-unicode branch from 87baa16 to f210262 Compare September 22, 2026 09:00
`resolve_name_template` walks the template as raw bytes and casts each one to `char`, which in Rust is a Latin-1 reinterpretation of the byte value. Substituted `{field}` values are fine (they go through `push_str` at line 71); the literal text around them is not. I confirmed the behaviour by compiling the same loop standalone: `résumé-{id}.mp4` yields `résumé-VAL.mp4` and `动画-{id}.mp4` yields `å¨ç»-VAL.mp4`. So `rustmotion batch --name-template "résumé-{id}.mp4"` writes files literally named `résumé-abc.mp4` to disk, and the same corruption lands in the `[ok] <path>` progress lines and in every failure message (`item N: ...`). A localisation batch — the exact use case `{lang}/{id}.mp4` in the module doc is built for — is where a non-ASCII template is most likely. None of the five tests in `name_template_tests` (lines 448-495) uses a non-ASCII template.

Refs #220
@LeadcodeDev
LeadcodeDev force-pushed the fix/batch-template-unicode branch from f210262 to 72c5ac4 Compare September 22, 2026 09:05
@LeadcodeDev
LeadcodeDev merged commit e068341 into chantier/audit-2026-09 Sep 22, 2026
LeadcodeDev added a commit that referenced this pull request Sep 22, 2026
`resolve_name_template` walks the template as raw bytes and casts each one to `char`, which in Rust is a Latin-1 reinterpretation of the byte value. Substituted `{field}` values are fine (they go through `push_str` at line 71); the literal text around them is not. I confirmed the behaviour by compiling the same loop standalone: `résumé-{id}.mp4` yields `résumé-VAL.mp4` and `动画-{id}.mp4` yields `å¨ç»-VAL.mp4`. So `rustmotion batch --name-template "résumé-{id}.mp4"` writes files literally named `résumé-abc.mp4` to disk, and the same corruption lands in the `[ok] <path>` progress lines and in every failure message (`item N: ...`). A localisation batch — the exact use case `{lang}/{id}.mp4` in the module doc is built for — is where a non-ASCII template is most likely. None of the five tests in `name_template_tests` (lines 448-495) uses a non-ASCII template.

Refs #220
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant