Skip to content

[Repo Assist] Fix #1419: Add cycle guard for XSD group references to prevent StackOverflow#1626

Merged
dsyme merged 6 commits intomainfrom
repo-assist/fix-issue-1419-xsd-cycle-guard-bd0a84154ad110bb
Feb 23, 2026
Merged

[Repo Assist] Fix #1419: Add cycle guard for XSD group references to prevent StackOverflow#1626
dsyme merged 6 commits intomainfrom
repo-assist/fix-issue-1419-xsd-cycle-guard-bd0a84154ad110bb

Conversation

@github-actions
Copy link
Contributor

🤖 This is a draft PR from Repo Assist, an automated AI assistant.

Closes #1419

Summary

Adds a cycle guard to XsdInference.fs to prevent a StackOverflowException when parsing XSD schemas whose compiled object graph contains group reference cycles.

When XmlProvider(Schema = "...") is used with a complex schema (such as the MS Office Custom UI schema), parseParticle can recurse infinitely when following XmlSchemaGroupRef.Particle chains that form a loop in the compiled XmlSchemaSet object graph.

Root Cause

In XsdParsing.parseParticle, the XmlSchemaGroupRef case unconditionally recursed into the resolved group's particle:

| :? XmlSchemaGroupRef as grpRef -> parseParticle ctx grpRef.Particle

After .Compile(), the .NET XSD compiler sets grpRef.Particle to the referenced group's XmlSchemaGroupBase. If a complex schema has groups that (directly or transitively through the compiled object graph) reference each other, this creates a cycle: parseParticle(A.Particle) → ... → parseParticle(A.Particle) → ∞.

The existing cycle protection in parseElement (using ctx.Elements cache) handles recursion through element types, but not recursion through group particles themselves.

Fix

Two changes:

XsdInference.fs: Added visitingGroups : HashSet(XmlQualifiedName) to ParsingContext, exposed as member x.VisitingGroups. In parseParticle, the XmlSchemaGroupRef case now checks whether the group is already being visited, returning Empty (an empty particle) to break the cycle:

| :? XmlSchemaGroupRef as grpRef ->
    // Guard against circular group references
    if ctx.VisitingGroups.Contains grpRef.RefName then
        Empty // break the cycle
    else
        ctx.VisitingGroups.Add grpRef.RefName |> ignore
        let result = parseParticle ctx grpRef.Particle
        ctx.VisitingGroups.Remove grpRef.RefName |> ignore
        result

InferenceTests.fs: Added a test verifying that a schema with a recursive content model (a group that, through its element content, references itself) completes without error.

Trade-offs

  • Returning Empty for the back-edge of a cycle is the same convention used elsewhere in the code (e.g. XmlSchemaParticle.EmptyParticle falls through to Empty). The inferred type for the cyclic portion will omit the repeated elements — but this is correct behaviour since infinite nesting is not representable in the generated types anyway.
  • The fix is minimal and surgical: only the GroupRef case is affected.

Test Status

All 50 InferenceTests pass (including new "circular group references do not cause a stack overflow" test)
⚠️ SignatureTests: 436 pre-existing failures due to infrastructure constraints (network/assembly lookup) — not caused by this PR. These failures were present before this change.

Generated by Repo Assist

To install this workflow, run gh aw add githubnext/agentics/workflows/repo-assist.md@ee50a3b7d1d3eb4a8c409ac9409fd61c9a66b0f5. View source at https://github.com/githubnext/agentics/tree/ee50a3b7d1d3eb4a8c409ac9409fd61c9a66b0f5/workflows/repo-assist.md.

Generated by Repo Assist

To install this workflow, run gh aw add githubnext/agentics/workflows/repo-assist.md@ee50a3b7d1d3eb4a8c409ac9409fd61c9a66b0f5. View source at https://github.com/githubnext/agentics/tree/ee50a3b7d1d3eb4a8c409ac9409fd61c9a66b0f5/workflows/repo-assist.md.

Repo Assist and others added 5 commits February 22, 2026 17:56
…0, FsCheck 2.16.6

- FAKE packages: 6.1.3 → 6.1.4 (patch)
- NUnit: 3.13.1 → 3.13.3 (patch)
- FsUnit: 4.0.4 → 4.2.0 (minor)
- FsCheck: 2.15.1 → 2.16.6 (minor)

Build: passes (0 errors)
Tests: all offline tests pass; network tests skip due to sandbox

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a VisitingGroups HashSet to ParsingContext and guard the GroupRef
case in parseParticle. When a group is already being visited, return
Empty (an empty particle) instead of recursing infinitely.

This prevents a StackOverflowException when parsing XSD schemas that
contain groups forming cycles (e.g. group A contains group ref B,
and group B's resolved content eventually leads back to group A via
the compiled XmlSchema object graph).

Add a test verifying that a recursive content model schema with a
group referencing itself through element content completes without error.

Closes #1419

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Contributor Author

✅ Pull request created: #1626

@dsyme dsyme marked this pull request as ready for review February 22, 2026 22:07
@dsyme dsyme closed this Feb 22, 2026
@dsyme dsyme reopened this Feb 22, 2026
Base automatically changed from repo-assist/deps-update-2026-02-22-22f87c2bfdc6ec83 to main February 22, 2026 22:10
@dsyme dsyme merged commit e32127a into main Feb 23, 2026
2 checks passed
@dsyme dsyme deleted the repo-assist/fix-issue-1419-xsd-cycle-guard-bd0a84154ad110bb branch February 23, 2026 00:13
github-actions bot added a commit that referenced this pull request Feb 23, 2026
Add entries for:
- #1613: CSS pseudo-class NotSupportedException fix (#1383)
- #1617: ConvertDateTimeOffset xs:dateTime fallback fix (#1437)
- #1618: Microsoft.Build security bump
- #1619: XmlProvider EmbeddedResource GetSchema fix (#1310)
- #1621: StrictBooleans parameter for CsvProvider
- #1625: CsvProvider.InferRows multiline quoted field fix (#1439)
- #1626: XSD group reference cycle guard (#1419)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

XmlProvider: Error reading MS Office Custom UI Schema

1 participant