@@ -378,8 +378,7 @@ impl HookExecutor {
378378
379379/// Sanitizes a string value to be used as an environment variable
380380fn sanitize_user_prompt ( input : & str ) -> String {
381- // Limit the size of input to first 4096 characters
382- let truncated = if input. len ( ) > 4096 { & input[ 0 ..4096 ] } else { input } ;
381+ let truncated = truncate_safe ( input, 4096 ) ;
383382
384383 // Remove any potentially problematic characters
385384 truncated. replace ( |c : char | c. is_control ( ) && c != '\n' && c != '\r' && c != '\t' , "" )
@@ -742,4 +741,31 @@ mod tests {
742741 assert_eq ! ( * exit_code, 0 ) ;
743742 assert ! ( hook_output. contains( "Turn completed successfully" ) ) ;
744743 }
744+
745+ #[ test]
746+ fn test_sanitize_user_prompt_cjk_characters ( ) {
747+ // Test with CJK characters that would cause panic with naive byte slicing
748+ let korean_text = "한" . repeat ( 2000 ) ; // Each Korean character is 3 bytes in UTF-8
749+ let result = sanitize_user_prompt ( & korean_text) ;
750+
751+ // Should not panic and should be truncated safely
752+ assert ! ( result. len( ) <= 4096 ) ;
753+ assert ! ( !result. is_empty( ) ) ;
754+
755+ // Test with mixed ASCII and CJK at boundary
756+ let mixed_text = "a" . repeat ( 4094 ) + "한국어" ; // 4094 + 9 bytes = 4103 bytes
757+ let result = sanitize_user_prompt ( & mixed_text) ;
758+ assert ! ( result. len( ) <= 4096 ) ;
759+ assert ! ( result. ends_with( "a" ) ) ; // Should end with ASCII, not partial CJK
760+
761+ // Test with text shorter than limit
762+ let short_text = "안녕하세요" ;
763+ let result = sanitize_user_prompt ( short_text) ;
764+ assert_eq ! ( result, short_text) ;
765+
766+ // Test with control characters
767+ let text_with_controls = "Hello\x00 World\n Test\r \t End" ;
768+ let result = sanitize_user_prompt ( text_with_controls) ;
769+ assert_eq ! ( result, "HelloWorld\n Test\r \t End" ) ;
770+ }
745771}
0 commit comments