Repository navigation
fix(cli): guard six byte-indexed slice sites against multibyte/overrun panics - #3451
yassine-ceo wants to merge 1 commit into
Conversation
…n panics Harden byte-indexed string slices that could panic on multi-byte input or when a trailing token is shorter than the fallback span. - utils.rs: round the 10-byte truncate_iso_date cut down to a char boundary (rtk-ai#3444) - prisma_cmd.rs: span a line-final migration token by the rest of the line, not a fixed 20 bytes (rtk-ai#3445) - find_cmd.rs: shorten_dir_display keeps trailing 47 bytes on a char boundary (rtk-ai#3415) - git.rs: parse_commit_output strips the leading '[' via strip_prefix so byte 1 is always a boundary (rtk-ai#3415) - gain.rs: short_month_day rounds the 5..10 slice to char boundaries (same class as rtk-ai#3415) - display_helpers.rs: WeekStats::period rounds the 5.. slice to char boundaries (same class as rtk-ai#3415) TDD: regression tests added for all six sites before each fix.
Overlapping git.rs/find_cmd.rs sites resolved in favour of rtk-ai#3435, which applies the same strip_prefix fix; rtk-ai#3451 contributes the remaining four sites (gain, prisma, display_helpers, utils).
|
Three of the six sites in this PR are already fixed on develop: parse_commit_output was rewritten by commit f496f59 (2026-08-15), find's directory label truncates by chars since #3603 (merged 2026-08-26), and filter_migrate_status got its fallback in #3836 (merged 2026-09-11). What develop still lacks are the other three byte-indexed slices and their regression tests: truncate_iso_date's |
Summary
Fixes a family of byte-indexed string slices that can panic on multi-byte input, plus one out-of-bounds overrun. Regression tests were added before each fix (TDD, Red-Green) and each test fails on the pre-fix code.
Byte-boundary panics (sliced mid-character)
truncate_iso_date(src/core/utils.rs) —&date[..10]sliced through a multi-byte character straddling byte 10. Closes truncate_iso_date byte-index slice panics on multi-byte UTF-8 input #3444. Now rounds the cut down to a char boundary:&date[..date.floor_char_boundary(10.min(date.len()))].parse_commit_output(src/cmds/git/git.rs) —&line[1..bracket_end]assumed byte 1 was a char boundary (panics on multibyte branch/author prefixes) and&line[1..0]on a line starting with]. Closesrtk findpanics on a non-ASCII directory path >50 bytes, andrtk git commitpanics when the first output line does not start with[#3415. Rewritten withstrip_prefix('[')+rest.find(']').finddir display (src/cmds/system/find_cmd.rs) —&dir[dir.len() - 47..]sliced through a multi-byte character. Closesrtk findpanics on a non-ASCII directory path >50 bytes, andrtk git commitpanics when the first output line does not start with[#3415. Extractedshorten_dir_displaywhich rounds down withfloor_char_boundary.short_month_day(src/analytics/gain.rs,print_ascii_graph) —&date[5..10]sliced through a multi-byte character. Same bug class asrtk findpanics on a non-ASCII directory path >50 bytes, andrtk git commitpanics when the first output line does not start with[#3415 (spawned from panic: rtk gain --history crashes on non-ASCII (Cyrillic) command strings — UTF-8 char boundary #2954), not previously filed. Now rounds both ends to char boundaries.WeekStats::period(src/core/display_helpers.rs) — two&s[5..]slices with the same multi-byte hazard. Same bug class asrtk findpanics on a non-ASCII directory path >50 bytes, andrtk git commitpanics when the first output line does not start with[#3415, not previously filed. Now rounds down to char boundaries.Out-of-bounds overrun
filter_migrate_status(src/cmds/js/prisma_cmd.rs) —unwrap_or(20)sliced past the end of a line when the migration token is line-final and shorter than 20 bytes. Closes prisma_cmd.rs migration-name slice panics with out-of-bounds index when token is short and line-final #3445. Now falls back toline.len() - pos, matching the existing migrate-dev path ~60 lines above.Testing
cargo test— 2549 passed; 16 failed are pre-existingcore::streamtests that spawn Unix-only binaries (sh,true,false,echo,cat) and cannot run on Windows (they run fine in Linux CI and are untouched by this PR).cargo fmt --all --check— cleancargo clippy --all-targets— cleanAll six new regression tests fail on the pre-fix code and pass after.