Skip to content

Conversation

@sayeedjoy
Copy link

Problem

The app kept crashing with a StackOverflowError on some Wikipedia pages because the toWikitextAnnotatedString function was getting stuck in an endless loop. Certain templates like {{small}} were sending the same wikitext back into the parser again and again, which caused the function to call itself repeatedly until the app crashed.

Stack Trace Sample

 at org.nsh07.wikireader.parser.WikitextToAnnotatedStringKt.toWikitextAnnotatedString(wikitextToAnnotatedString.kt:592)
  at org.nsh07.wikireader.parser.WikitextToAnnotatedStringKt$$ExternalSyntheticLambda1.invoke(D8$$SyntheticClass:0)
  at org.nsh07.wikireader.parser.WikitextToAnnotatedStringKt.toWikitextAnnotatedString(wikitextToAnnotatedString.kt:592)
  at org.nsh07.wikireader.parser.WikitextToAnnotatedStringKt$$ExternalSyntheticLambda1.invoke(D8$$SyntheticClass:0)

Solution

Implemented a two-part fix:

1. Recursion Depth Guard

  • Added a thread-local recursion counter with a maximum depth of 64 nested parsing calls
  • When the limit is reached, the parser returns plain text (AnnotatedString(this)) instead of crashing
  • The guard uses a try/finally block to ensure proper cleanup of the recursion counter

2. Template Branch Hardening

  • Fixed multiple template handlers that could cause infinite recursion when used without parameters
  • Changed substringAfter('|') to substringAfter('|', "") for templates like:
    • {{abbr}}, {{efn}}, {{val}}, {{var}}, {{small}} family, {{dfn}}, {{US$}}, {{hatnote}}, {{rp}}, {{isbn}}, {{sfrac}}, {{unichar}}, {{char}}, {{noflag}}, {{nowrap}} family, {{url}}, {{format price}}, {{transliteration}}
  • This ensures that when a template has no | parameter, the parser receives an empty string instead of the full template text, preventing self-recursion

Changes

  • File: app/src/main/java/org/nsh07/wikireader/parser/wikitextToAnnotatedString.kt
    • Added MAX_WIKITEXT_RECURSION_DEPTH constant (64)
    • Added WikitextParserState object with thread-local recursion counter
    • Added recursion guard at the start of toWikitextAnnotatedString function
    • Hardened 20+ template branches to prevent infinite recursion

Testing

  • Verified no compilation errors
  • Test on previously crashing Wikipedia pages
  • Verify normal content (links, headings, references, templates) still renders correctly
  • Confirm app no longer crashes with StackOverflowError

Notes

  • In extreme edge cases with deeply nested or malformed templates, the parser may display raw wikitext instead of fully parsed content. This is intentional to prevent crashes.
  • The recursion limit of 64 should be sufficient for all legitimate Wikipedia content while preventing runaway recursion.

Copilot AI review requested due to automatic review settings December 5, 2025 17:07
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a critical infinite recursion bug in the wikitext parser that was causing StackOverflowError crashes when parsing certain Wikipedia templates. The solution implements a two-pronged approach: a recursion depth guard and hardening of template parameter extraction.

Key changes:

  • Added a ThreadLocal recursion depth counter with a maximum depth of 64 to gracefully handle deeply nested or malformed wikitext
  • Fixed 18+ template handlers to use substringAfter('|', "") with an empty string default, preventing self-recursion when templates lack parameters

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@nsh07
Copy link
Owner

nsh07 commented Dec 7, 2025

Looks good to me. Can you please fix the changes Copilot has suggested? Otherwise it's good.

sayeedjoy and others added 2 commits December 7, 2025 13:41
…tedString.kt

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…tedString.kt

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@sayeedjoy
Copy link
Author

Looks good to me. Can you please fix the changes Copilot has suggested? Otherwise it's good.

Copilot suggestions accepted.

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.

2 participants