@@ -465,20 +465,60 @@ func builtinRegexReplaceInternal(args []Value, kwargs map[string]Value, block Va
465465 if len (text ) > maxRegexInputBytes {
466466 return NewNil (), fmt .Errorf ("%s text exceeds limit %d bytes" , method , maxRegexInputBytes )
467467 }
468+ if len (replacement ) > maxRegexInputBytes {
469+ return NewNil (), fmt .Errorf ("%s replacement exceeds limit %d bytes" , method , maxRegexInputBytes )
470+ }
468471
469472 re , err := regexp .Compile (pattern )
470473 if err != nil {
471474 return NewNil (), fmt .Errorf ("%s invalid regex: %v" , method , err )
472475 }
473476
474477 if replaceAll {
475- return NewString (re .ReplaceAllString (text , replacement )), nil
478+ replaced , err := regexReplaceAllWithLimit (re , text , replacement , method )
479+ if err != nil {
480+ return NewNil (), err
481+ }
482+ return NewString (replaced ), nil
476483 }
477484
478485 loc := re .FindStringSubmatchIndex (text )
479486 if loc == nil {
480487 return NewString (text ), nil
481488 }
482489 replaced := string (re .ExpandString (nil , replacement , text , loc ))
490+ outputLen := len (text ) - (loc [1 ] - loc [0 ]) + len (replaced )
491+ if outputLen > maxRegexInputBytes {
492+ return NewNil (), fmt .Errorf ("%s output exceeds limit %d bytes" , method , maxRegexInputBytes )
493+ }
483494 return NewString (text [:loc [0 ]] + replaced + text [loc [1 ]:]), nil
484495}
496+
497+ func regexReplaceAllWithLimit (re * regexp.Regexp , text string , replacement string , method string ) (string , error ) {
498+ matches := re .FindAllStringSubmatchIndex (text , - 1 )
499+ if len (matches ) == 0 {
500+ return text , nil
501+ }
502+
503+ out := make ([]byte , 0 , len (text ))
504+ last := 0
505+ for _ , loc := range matches {
506+ segmentLen := loc [0 ] - last
507+ if len (out ) > maxRegexInputBytes - segmentLen {
508+ return "" , fmt .Errorf ("%s output exceeds limit %d bytes" , method , maxRegexInputBytes )
509+ }
510+ out = append (out , text [last :loc [0 ]]... )
511+ out = re .ExpandString (out , replacement , text , loc )
512+ if len (out ) > maxRegexInputBytes {
513+ return "" , fmt .Errorf ("%s output exceeds limit %d bytes" , method , maxRegexInputBytes )
514+ }
515+ last = loc [1 ]
516+ }
517+
518+ tailLen := len (text ) - last
519+ if len (out ) > maxRegexInputBytes - tailLen {
520+ return "" , fmt .Errorf ("%s output exceeds limit %d bytes" , method , maxRegexInputBytes )
521+ }
522+ out = append (out , text [last :]... )
523+ return string (out ), nil
524+ }
0 commit comments