jenkins-bot has submitted this change. ( 
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1322836?usp=email )

Change subject: [FIX] Prevent infinite recursion loop in 
fix_moved_broken_redirects
......................................................................

[FIX] Prevent infinite recursion loop in fix_moved_broken_redirects

Add visited set to track checked target pages during recursive lookup
to prevent cyclic move target loops.

Bug: T432620
Change-Id: Ib4e1a4f8954938b4f14bc660aa8f58d7a19ea5f5
---
M scripts/redirect.py
M tests/redirect_bot_tests.py
2 files changed, 44 insertions(+), 2 deletions(-)

Approvals:
  jenkins-bot: Verified
  Mahveotm: Looks good to me, approved




diff --git a/scripts/redirect.py b/scripts/redirect.py
index cb19913..44eec6c 100755
--- a/scripts/redirect.py
+++ b/scripts/redirect.py
@@ -490,18 +490,36 @@
             pywikibot.info(f'{page} is on another site, skipping.')
         return None

-    def fix_moved_broken_redirects(self, target: pywikibot.Page) -> None:
+    def fix_moved_broken_redirects(
+        self,
+        target: pywikibot.Page,
+        visited: set[pywikibot.Page] | None = None,
+    ) -> None:
         """Try to fix a deleted redirect using moved_target method."""
         redir_page = self.current_page
         done = not self.opt.delete
         movedTarget = None

+        if visited is None:
+            visited = {redir_page}
+
+        if target in visited:
+            pywikibot.info(f'Redirect target {target} forms a redirect loop')
+            return
+
+        visited.add(target)
+
         with suppress(NoMoveTargetError):
             movedTarget = target.moved_target()

         if movedTarget:
+            if movedTarget in visited:
+                pywikibot.info(
+                    f'Redirect target {movedTarget} forms a redirect loop')
+                return
+
             if not movedTarget.exists():
-                self.fix_moved_broken_redirects(movedTarget)
+                self.fix_moved_broken_redirects(movedTarget, visited=visited)
                 # process other cases within recursive loop
                 return

diff --git a/tests/redirect_bot_tests.py b/tests/redirect_bot_tests.py
index defa8be..9edf82c 100755
--- a/tests/redirect_bot_tests.py
+++ b/tests/redirect_bot_tests.py
@@ -71,6 +71,30 @@
         w.assert_called_with('No speedy deletion template "n" available.')


+class TestFixMovedBrokenRedirects(DefaultSiteTestCase):
+
+    """Test fix_moved_broken_redirects() loop handling."""
+
+    def test_cyclic_move_chain_terminates_without_editing_or_deleting(
+            self) -> None:
+        """Move chain A -> B -> C -> A must terminate without edits."""
+        page_a, page_b, page_c = Mock(), Mock(), Mock()
+        page_a.moved_target.return_value = page_b
+        page_b.moved_target.return_value = page_c
+        page_c.moved_target.return_value = page_a  # closes the loop
+        page_b.exists.return_value = False
+        page_c.exists.return_value = False
+
+        bot = RedirectTestRobot('broken', delete=True)
+        bot.delete_redirect = Mock()
+        bot.userPut = Mock(return_value=True)
+
+        bot.fix_moved_broken_redirects(page_a)  # must not hang/recurse
+
+        bot.delete_redirect.assert_not_called()
+        bot.userPut.assert_not_called()
+
+
 if __name__ == '__main__':
     with suppress(SystemExit):
         unittest.main()

--
To view, visit 
https://gerrit.wikimedia.org/r/c/pywikibot/core/+/1322836?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.wikimedia.org/r/settings?usp=email

Gerrit-MessageType: merged
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: Ib4e1a4f8954938b4f14bc660aa8f58d7a19ea5f5
Gerrit-Change-Number: 1322836
Gerrit-PatchSet: 3
Gerrit-Owner: Raushan 31 <[email protected]>
Gerrit-Reviewer: Mahveotm <[email protected]>
Gerrit-Reviewer: Xqt <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
Pywikibot-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to