Bug: UTF-8 char-boundary panic in `summarize_patch_for_logging` on non-ASCII patches

Open Beginner friendly
#35,381 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
1/5
Estimated time
Under an hour
Newbie friendliness
90/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
rust
Domain
cli

Research direction

Start in cloud-tasks-client/src/http.rs at summarize_patch_for_logging, especially the truncation around line 901. Reproduce it with a non-ASCII patch whose first 20 lines exceed 800 bytes, then verify that truncation no longer panics and ends at a complete UTF-8 character before the ellipsis.

Written by the indexing model from the issue text.

Description

bug CLI
What version of Codex CLI is running?

Reproduced with codex-cli 0.145.0. The same implementation is still present in main at e4fb5311d7468839def62eabda4b268f4a54cf11.

What platform is your computer?

Darwin 26.5.2 arm64 arm (macOS).

What issue are you seeing?

summarize_patch_for_logging panics when a patch contains non-ASCII characters (e.g., file paths with UTF-8 characters like Chinese, Japanese, accented Latin, emoji) and the truncation point falls in the middle of a multi-byte character.

Root cause: Line 901 uses a byte-level slice:

let head_trunc = if head.len() > 800 {
    format!("{}…", &head[..800])  // panics if byte 800 is not a char boundary
} else {
    head
};

&head[..800] is a byte-level index. If the 800th byte falls in the middle of a multi-byte UTF-8 character (e.g., a 3-byte CJK character, a 4-byte emoji), Rust panics with:

byte index 800 is not a char boundary; it is inside '某' (bytes 798..801)

This is a logging function (summarize_patch_for_logging), so it won't lose user data, but it will abort the logging call and could unwind a ? chain upstream depending on the call site.

What steps can reproduce the bug?
  1. Create a file with a non-ASCII name or content that exceeds 800 bytes when the first 20 lines are joined
  2. Use apply_patch to modify that file
  3. The logging function panics when truncating

Alternatively, construct a patch string where bytes 798-800 contain a multi-byte character and call summarize_patch_for_logging directly.

What is the expected behavior?

The truncation should respect UTF-8 character boundaries. The function should truncate at the last complete character before byte 800.

Suggested fix

Replace &head[..800] with a char-boundary-safe truncation. Two options:

Option A (using floor_char_boundary, stable since Rust 1.73):

let head_trunc = if head.len() > 800 {
    let boundary = head.floor_char_boundary(800);
    format!("{}…", &head[..boundary])
} else {
    head
};

Option B (using char_indices, already used elsewhere in the codebase):

let head_trunc = if head.len() > 800 {
    let boundary = head.char_indices()
        .take_while(|(i, _)| *i <= 800)
        .last()
        .map(|(i, _)| i)
        .unwrap_or(800);
    format!("{}…", &head[..boundary])
} else {
    head
};

The Rust toolchain is pinned to 1.95.0, so floor_char_boundary is available and is the cleanest option.

Related

Similar class of bug to #34282 (rollout trace reducer panics on non-ASCII JSON truncation). This suggests a pattern of byte-level truncation across the codebase that should be audited for UTF-8 safety.

Scope

Single-line fix in one file (cloud-tasks-client/src/http.rs:901). No behavioral change — only the truncation boundary is made UTF-8-safe.

Dominant language
Rust
Stars
125k
Forks
19.5k
Avg merge
1m
Merged PRs (30d)
1k

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from openai/codex

All issues in openai/codex

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.