diff --git a/processor/regex.go b/processor/regex.go index 0060934..62a4e0f 100644 --- a/processor/regex.go +++ b/processor/regex.go @@ -208,6 +208,8 @@ func (p *RegexProcessor) ProcessContent(content string, pattern string, luaExpr } } + captureGroups = deduplicateGroups(captureGroups) + if err := p.ToLua(L, captureGroups); err != nil { logger.Error("Failed to set Lua variables: %v", err) continue @@ -285,6 +287,14 @@ func (p *RegexProcessor) ProcessContent(content string, pattern string, luaExpr for _, command := range commands { logger.Trace("Replace pos %d-%d with %q", command.From, command.To, command.With) + if command.To < command.From { + logger.Error("Command to is less than from: %v", command) + continue + } + if command.From > len(replacement) || command.To > len(replacement) { + logger.Error("Command from or to is greater than replacement length: %v", command) + continue + } replacement = replacement[:command.From] + command.With + replacement[command.To:] } } @@ -305,6 +315,30 @@ func (p *RegexProcessor) ProcessContent(content string, pattern string, luaExpr return result, modificationCount, len(indices), nil } +func deduplicateGroups(captureGroups []*CaptureGroup) []*CaptureGroup { + deduplicatedGroups := make([]*CaptureGroup, 0) + for _, group := range captureGroups { + overlaps := false + logger.Debug("Checking capture group: %s with range %v", group.Name, group.Range) + for _, existingGroup := range deduplicatedGroups { + logger.Debug("Comparing with existing group: %s with range %v", existingGroup.Name, existingGroup.Range) + if group.Range[0] < existingGroup.Range[1] && group.Range[1] > existingGroup.Range[0] { + overlaps = true + logger.Warning("Detected overlap between capture group '%s' and existing group '%s' in range %v-%v and %v-%v", group.Name, existingGroup.Name, group.Range[0], group.Range[1], existingGroup.Range[0], existingGroup.Range[1]) + break + } + } + if overlaps { + // We CAN just continue despite this fuckup + logger.Error("Overlapping capture group: %s", group.Name) + continue + } + logger.Debug("No overlap detected for capture group: %s. Adding to deduplicated groups.", group.Name) + deduplicatedGroups = append(deduplicatedGroups, group) + } + return deduplicatedGroups +} + // The order of these replaces is important // This one handles !num-s inside of named capture groups // If it were not here our !num in a named capture group would diff --git a/regression/regression_test.go b/regression/regression_test.go index c04101f..6e5252b 100644 --- a/regression/regression_test.go +++ b/regression/regression_test.go @@ -3,6 +3,7 @@ package regression import ( "modify/processor" "os" + "path/filepath" "testing" ) @@ -83,13 +84,18 @@ func TestTalentsMechanicOutOfRange(t *testing.T) { } } -func TestIndexExplosions(t *testing.T) { - given, err := os.ReadFile("testfiles/OutpostItems.xml") +func TestIndexExplosions_ShouldNotPanic(t *testing.T) { + cwd, err := os.Getwd() + if err != nil { + t.Fatalf("Error getting current working directory: %v", err) + } + + given, err := os.ReadFile(filepath.Join(cwd, "..", "testfiles", "OutpostItems.xml")) if err != nil { t.Fatalf("Error reading file: %v", err) } - expected, err := os.ReadFile("testfiles/OutpostItemsExpected.xml") + expected, err := os.ReadFile(filepath.Join(cwd, "..", "testfiles", "OutpostItemsExpected.xml")) if err != nil { t.Fatalf("Error reading file: %v", err) }