@@ -357,31 +357,47 @@ fn validate_export_messages(messages: &[ExportMessage]) -> Result<()> {
357357 for ( idx, message) in messages. iter ( ) . enumerate ( ) {
358358 // Check for base64-encoded image data in content
359359 // Common pattern: "data:image/png;base64,..." or "data:image/jpeg;base64,..."
360- if let Some ( data_uri_start) = message. content . find ( "data:image/" )
361- && let Some ( base64_marker) = message. content [ data_uri_start..] . find ( ";base64," )
362- {
363- let base64_start = data_uri_start + base64_marker + 8 ; // 8 = len(";base64,")
364- let remaining = & message. content [ base64_start..] ;
365-
366- // Find end of base64 data (could end with quote, whitespace, or end of string)
367- let base64_end = remaining
368- . find ( [ '"' , '\'' , ' ' , '\n' , ')' ] )
369- . unwrap_or ( remaining. len ( ) ) ;
370- let base64_data = & remaining[ ..base64_end] ;
371-
372- // Validate the base64 data
373- if !base64_data. is_empty ( ) {
374- let engine = base64:: engine:: general_purpose:: STANDARD ;
375- if let Err ( e) = engine. decode ( base64_data) {
376- bail ! (
377- "Invalid base64 encoding in message {} (role: '{}'): {}\n \
378- The image data starting at position {} has invalid base64 encoding.\n \
379- Please ensure all embedded images use valid base64 encoding.",
380- idx + 1 ,
381- message. role,
382- e,
383- data_uri_start
384- ) ;
360+ if let Some ( data_uri_start) = message. content . find ( "data:image/" ) {
361+ // Use safe slicing with .get() to avoid panics on multi-byte UTF-8 boundaries
362+ let content_after_start = match message. content . get ( data_uri_start..) {
363+ Some ( s) => s,
364+ None => continue , // Invalid byte offset, skip this message
365+ } ;
366+
367+ if let Some ( base64_marker) = content_after_start. find ( ";base64," ) {
368+ let base64_start = data_uri_start + base64_marker + 8 ; // 8 = len(";base64,")
369+
370+ // Safe slicing for the remaining content after base64 marker
371+ let remaining = match message. content . get ( base64_start..) {
372+ Some ( s) => s,
373+ None => continue , // Invalid byte offset, skip this message
374+ } ;
375+
376+ // Find end of base64 data (could end with quote, whitespace, or end of string)
377+ let base64_end = remaining
378+ . find ( [ '"' , '\'' , ' ' , '\n' , ')' ] )
379+ . unwrap_or ( remaining. len ( ) ) ;
380+
381+ // Safe slicing for the base64 data
382+ let base64_data = match remaining. get ( ..base64_end) {
383+ Some ( s) => s,
384+ None => continue , // Invalid byte offset, skip this message
385+ } ;
386+
387+ // Validate the base64 data
388+ if !base64_data. is_empty ( ) {
389+ let engine = base64:: engine:: general_purpose:: STANDARD ;
390+ if let Err ( e) = engine. decode ( base64_data) {
391+ bail ! (
392+ "Invalid base64 encoding in message {} (role: '{}'): {}\n \
393+ The image data starting at position {} has invalid base64 encoding.\n \
394+ Please ensure all embedded images use valid base64 encoding.",
395+ idx + 1 ,
396+ message. role,
397+ e,
398+ data_uri_start
399+ ) ;
400+ }
385401 }
386402 }
387403 }
@@ -395,13 +411,24 @@ fn validate_export_messages(messages: &[ExportMessage]) -> Result<()> {
395411 // Try to find and validate any base64 in the arguments
396412 for ( pos, _) in args_str. match_indices ( ";base64," ) {
397413 let base64_start = pos + 8 ;
398- let remaining = & args_str[ base64_start..] ;
414+
415+ // Safe slicing for the remaining content after base64 marker
416+ let remaining = match args_str. get ( base64_start..) {
417+ Some ( s) => s,
418+ None => continue , // Invalid byte offset, skip this occurrence
419+ } ;
420+
399421 let base64_end = remaining
400422 . find ( |c : char | {
401423 c == '"' || c == '\'' || c == ' ' || c == '\n' || c == ')'
402424 } )
403425 . unwrap_or ( remaining. len ( ) ) ;
404- let base64_data = & remaining[ ..base64_end] ;
426+
427+ // Safe slicing for the base64 data
428+ let base64_data = match remaining. get ( ..base64_end) {
429+ Some ( s) => s,
430+ None => continue , // Invalid byte offset, skip this occurrence
431+ } ;
405432
406433 if !base64_data. is_empty ( ) {
407434 let engine = base64:: engine:: general_purpose:: STANDARD ;
0 commit comments