From 5fc3273e78341092a0ff719598a73f9bdd7460b1 Mon Sep 17 00:00:00 2001 From: Liet Blue Date: Mon, 13 Apr 2026 16:55:56 +0800 Subject: [PATCH] fix(guard): use UTF-8 safe string truncation in output preview logging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `label_response` panics when the serialized output JSON contains multi-byte UTF-8 characters (CJK, emoji) and byte index 500 falls mid-character. Replace `&output_json[..500]` with `floor_char_boundary(500)` which finds the nearest char boundary. This crash poisons the WASM guard for the entire session — all subsequent MCP calls fail with "unavailable after a previous trap". Discovered via moeru-ai/airi PR triage workflow (run #24311673575) on a PR with Chinese text in the body. --- guards/github-guard/rust-guard/src/lib.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/guards/github-guard/rust-guard/src/lib.rs b/guards/github-guard/rust-guard/src/lib.rs index 8e7960f9..1371c023 100644 --- a/guards/github-guard/rust-guard/src/lib.rs +++ b/guards/github-guard/rust-guard/src/lib.rs @@ -804,11 +804,10 @@ pub extern "C" fn label_response( }; // Log output preview for debugging - let output_preview = if output_json.len() > 500 { - &output_json[..500] - } else { - &output_json - }; + // NOTICE: Use floor_char_boundary to avoid panicking on multi-byte + // UTF-8 characters (CJK, emoji, etc.) when byte 500 falls mid-char. + let preview_end = output_json.floor_char_boundary(500); + let output_preview = &output_json[..preview_end]; log_info(&format!(" path_output_preview={}", output_preview)); if output_json.len() as u32 > output_size { @@ -935,11 +934,10 @@ pub extern "C" fn label_response( }; // Log output preview for debugging - let output_preview = if output_json.len() > 500 { - &output_json[..500] - } else { - &output_json - }; + // NOTICE: Use floor_char_boundary to avoid panicking on multi-byte + // UTF-8 characters (CJK, emoji, etc.) when byte 500 falls mid-char. + let preview_end = output_json.floor_char_boundary(500); + let output_preview = &output_json[..preview_end]; log_info(&format!(" output_preview={}", output_preview)); if output_json.len() as u32 > output_size {