Skip to content

Fix StackOverflowError deleting a bookmark folder with a relation cycle - #9704

Open
Asgabani wants to merge 1 commit into
duckduckgo:developfrom
Asgabani:fix/bookmark-folder-cycle-stackoverflow-5928
Open

Fix StackOverflowError deleting a bookmark folder with a relation cycle#9704
Asgabani wants to merge 1 commit into
duckduckgo:developfrom
Asgabani:fix/bookmark-folder-cycle-stackoverflow-5928

Conversation

@Asgabani

@Asgabani Asgabani commented Sep 3, 2026

Copy link
Copy Markdown

Summary

Fixes #5928.

RealSavedSitesRepository.traverseBranch() walked the bookmark folder tree via unbounded recursion, with no protection against a cycle in the relations table. If the relations table ever ends up with a folder cycle (corrupted/inconsistent data), traversal recurses forever and the app crashes with a StackOverflowError — matching the reported crash trace, which shows traverseBranch recursing repeatedly during a folder delete.

Fix

Replaces the recursive traversal with an iterative one (ArrayDeque + a visited-folder Set), so a folder that's already been visited is skipped instead of revisited indefinitely. Traversal order/output is unchanged for normal (acyclic) folder trees.

Test plan

  • Added whenFolderRelationsContainACycleThenGetFolderBranchTerminatesWithoutDuplicates, which inserts a corrupted cyclic relation (folderA ↔ folderB) directly via the DAOs and asserts getFolderBranch terminates and returns each folder exactly once.
  • Ran the full SavedSitesRepositoryTest suite (65 tests) — all pass, including every existing getFolderBranch/deleteFolderBranch test.
  • spotlessApply run, diff is clean.

Note

Low Risk
Localized change to private folder traversal with a regression test; behavior for valid trees is intended to stay the same while only corrupt cyclic data is handled differently.

Overview
Fixes #5928 by hardening bookmark folder branch traversal when the relations table contains a folder cycle (corrupted data), which previously caused unbounded recursion and a StackOverflowError during operations like folder delete that call getFolderBranch.

RealSavedSitesRepository.traverseBranch() is changed from recursive depth-first walking to an iterative ArrayDeque loop with a visited-folder set, so already-seen folder IDs are skipped instead of re-entered forever. Acyclic trees should behave the same; cycles terminate with each folder listed once.

Adds whenFolderRelationsContainACycleThenGetFolderBranchTerminatesWithoutDuplicates, seeding a cyclic folderA ↔ folderB relation via DAOs and asserting getFolderBranch completes with expected folder and bookmark counts.

Reviewed by Cursor Bugbot for commit e17b41d. Bugbot is set up for automated code reviews on this repo. Configure here.

@Asgabani
Asgabani requested a review from malmstein as a code owner September 3, 2026 13:41

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 69f35ac. Configure here.

Comment thread CHANGELOG_IMPROVEMENTS.md Outdated
@Asgabani

Asgabani commented Sep 4, 2026

Copy link
Copy Markdown
Author

Hello Team,

Please check the changes and if you satisfied with the changes , approve them and let me help make our duckduckgo better

Thank you
Ankit GabanI

@brianhall @brindy @claude @tagawa

traverseBranch() walked the folder tree with unbounded recursion and no
cycle detection. If the relations table ever contains a folder cycle
(corrupted data), it recurses forever and crashes with a
StackOverflowError.

Replaces the recursion with an iterative traversal guarded by a visited
set, so a cycle is skipped instead of looped over indefinitely.

Fixes duckduckgo#5928
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Got a StackOverflowError sometimes after delete a bookmark folder

1 participant